Finish up symlink support for both the loopback and real filesystem.
http://code.google.com/p/iphonedisk/source/detail?r=104
Modified:
/trunk/fs/fs_fuse.cc
/trunk/mobilefs/mobile_fs_service.cc
/trunk/mobilefs/mobiledevice.h
/trunk/proto/fs.proto
/trunk/proto/fs_service.proto
/trunk/test/loopback_fs_service.cc
=======================================
--- /trunk/fs/fs_fuse.cc Sat Oct 9 23:28:21 2010
+++ /trunk/fs/fs_fuse.cc Sun Oct 10 00:02:22 2010
@@ -85,6 +85,19 @@
strncpy(buf, response.destination().c_str(), bufsize);
return 0;
}
+
+int fs_symlink(const char* source, const char* target) {
+ struct Context* context =
+ static_cast<struct Context*>(fuse_get_context()->private_data);
+ rpc::Rpc rpc;
+ proto::SymLinkRequest request;
+ proto::SymLinkResponse response;
+ request.mutable_header()->set_fs_id(context->fs_id);
+ request.set_source(source);
+ request.set_target(target);
+ context->service->SymLink(&rpc, &request, &response, g_null_callback);
+ return rpc.Failed() ? -ENOENT : 0;
+}
int fs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi) {
@@ -285,6 +298,7 @@
fuse_op->destroy = fs_destroy;
fuse_op->getattr = fs_getattr;
fuse_op->readlink = fs_readlink;
+ fuse_op->symlink = fs_symlink;
fuse_op->readdir = fs_readdir;
fuse_op->open = fs_open;
fuse_op->create = fs_create;
=======================================
--- /trunk/mobilefs/mobile_fs_service.cc Sat Oct 9 22:35:38 2010
+++ /trunk/mobilefs/mobile_fs_service.cc Sun Oct 10 00:02:22 2010
@@ -51,6 +51,8 @@
}
if (info_map["st_ifmt"] == "S_IFDIR") {
stat->set_mode(S_IFDIR);
+ } else if (info_map["st_ifmt"] == "S_IFLNK") {
+ stat->set_mode(S_IFLNK);
} else if (info_map["st_ifmt"] == "S_IFREG") {
stat->set_mode(S_IFREG);
} else if (info_map["st_ifmt"] == "S_IFSOCK") {
@@ -77,6 +79,40 @@
}
done->Run();
}
+
+ void ReadLink(RpcController* rpc,
+ const proto::ReadLinkRequest* request,
+ proto::ReadLinkResponse* response,
+ Closure* done) {
+ struct afc_dictionary *info;
+ if (AFCFileInfoOpen(conn_, (char*)request->path().c_str(),
+ &info) != MDERR_OK) {
+ rpc->SetFailed("AFCFileInfoOpen failed");
+ } else {
+ std::map<std::string, std::string> info_map;
+ CreateMap(info, &info_map);
+ AFCKeyValueClose(info);
+ if (!info_map.count("LinkTarget")) {
+ rpc->SetFailed("AFCFileInfoOpen: Not a link");
+ } else {
+ response->set_destination(info_map["LinkTarget"]);
+ }
+ }
+ done->Run();
+ }
+
+ void SymLink(RpcController* rpc,
+ const proto::SymLinkRequest* request,
+ proto::SymLinkResponse* response,
+ Closure* done) {
+ int ret = AFCLinkPath(conn_, /* soft */ 2,
+ request->source().c_str(),
+request->target().c_str());
+ if (ret != MDERR_OK) {
+ rpc->SetFailed("AFCLinkPath failed");
+ }
+ done->Run();
+ }
void ReadDir(RpcController* rpc,
const proto::ReadDirRequest* request,
@@ -278,6 +314,7 @@
std::map<std::string, std::string>* out) {
char *key, *val;
while ((AFCKeyValueRead(in, &key, &val) == MDERR_OK) && key && val) {
+printf("%s => %s\n", key, val);
(*out)[key] = val;
}
}
=======================================
--- /trunk/mobilefs/mobiledevice.h Sat Apr 10 21:18:11 2010
+++ /trunk/mobilefs/mobiledevice.h Sun Oct 10 00:02:22 2010
@@ -111,12 +111,8 @@
unsigned int unknown2; /* 32 - reference counter, increased by
AMDeviceRetain, decreased by AMDeviceRelease*/
unsigned int lockdown_conn; /* 36 */
unsigned char unknown3[8]; /* 40 */
-#if (__ITUNES_VER > 740)
unsigned int unknown4; /* 48 - used to store CriticalSection
Handle*/
-#endif
-#if (__ITUNES_VER >= 800)
unsigned char unknown5[24]; /* 52 */
-#endif
} __PACK;
struct am_device_notification {
@@ -394,7 +390,6 @@
afc_error_t AFCRenamePath(afc_connection *conn, const char *oldpath,
const char *newpath);
-#if (__ITUNES_VER >= 800)
/* Creates symbolic or hard link
* linktype - int64: 1 means hard link, 2 - soft (symbolic) link
* target - absolute or relative path to link target
@@ -403,7 +398,6 @@
afc_error_t AFCLinkPath(struct afc_connection *conn, long long int
linktype, const char *target,
const char *linkname);
-#endif
/* Opens file for reading or writing without locking it in any way.
afc_file_ref should not be shared between threads -
* opening file in one thread and closing it in another will lead
to possible crash.
* path - UTF-8 encoded absolute path to file
=======================================
--- /trunk/proto/fs.proto Sat Oct 9 23:28:21 2010
+++ /trunk/proto/fs.proto Sun Oct 10 00:02:22 2010
@@ -35,6 +35,15 @@
message ReadLinkResponse {
optional string destination = 1;
}
+
+message SymLinkRequest {
+ required Header header = 1;
+ required string source = 2;
+ required string target = 3;
+}
+
+message SymLinkResponse {
+}
message ReadDirRequest {
required Header header = 1;
@@ -44,7 +53,6 @@
message ReadDirResponse {
message Entry {
required string filename = 1;
- optional Stat stat = 2;
}
repeated Entry entry = 1;
}
=======================================
--- /trunk/proto/fs_service.proto Sat Oct 9 23:28:21 2010
+++ /trunk/proto/fs_service.proto Sun Oct 10 00:02:22 2010
@@ -9,6 +9,7 @@
service FsService {
rpc GetAttr (GetAttrRequest) returns (GetAttrResponse);
rpc ReadLink (ReadLinkRequest) returns (ReadLinkResponse);
+ rpc SymLink (SymLinkRequest) returns (SymLinkResponse);
rpc ReadDir (ReadDirRequest) returns (ReadDirResponse);
rpc Open (OpenRequest) returns (OpenResponse);
rpc Create (CreateRequest) returns (CreateResponse);
=======================================
--- /trunk/test/loopback_fs_service.cc Sat Oct 9 23:28:21 2010
+++ /trunk/test/loopback_fs_service.cc Sun Oct 10 00:02:22 2010
@@ -55,6 +55,17 @@
}
done->Run();
}
+
+ void SymLink(RpcController* rpc,
+ const proto::SymLinkRequest* request,
+ proto::SymLinkResponse* response,
+ Closure* done) {
+ int ret = symlink(request->source().c_str(),
request->target().c_str());
+ if (ret == -1) {
+ rpc->SetFailed(strerror(errno));
+ }
+ done->Run();
+ }
void ReadDir(RpcController* rpc,
const proto::ReadDirRequest* request,