1 /* usmb - mount SMB shares via FUSE and Samba
2 * Copyright (C) 2006-2007 Geoff Johnstone
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <sys/time.h> // struct timeval needed by libsmbclient.h
20 #include <sys/types.h>
23 #include <libsmbclient.h>
37 #include "usmb_file.h"
43 static char *server
, *share
, *mountpoint
, *options
,
44 *domain
, *username
, *password
;
47 char * make_url (const char *path
)
49 assert (NULL
!= share
);
51 if ((NULL
== path
) || ('\0' == path
[0]))
52 return xstrdup (share
);
54 return concat_strings (2, share
, path
);
58 static inline void do_strncpy (char *to
, const char *from
, int tolen
)
60 strncpy (to
, from
, tolen
);
65 static void auth_fn (const char *srv
, const char *shr
, char *wg
, int wglen
,
66 char *un
, int unlen
, char *pw
, int pwlen
)
70 DEBUG (fprintf (stderr
, "Authenticating for \\\\%s\\%s\n", srv
, shr
));
71 DEBUG (fprintf (stderr
, "Domain: %s; User: %s; Password:%s\n",
72 domain
, username
, password
));
75 do_strncpy (wg
, domain
, wglen
);
77 do_strncpy (un
, username
, unlen
);
78 do_strncpy (pw
, password
, pwlen
);
82 static bool create_smb_context (char *domain
, char *username
, SMBCCTX
**pctx
)
84 *pctx
= smbc_new_context();
88 perror ("Cannot create SMB context");
92 (*pctx
)->workgroup
= domain
;
93 (*pctx
)->user
= username
;
94 (*pctx
)->timeout
= 5000;
95 (*pctx
)->callbacks
.auth_fn
= auth_fn
;
97 if (NULL
== smbc_init_context (*pctx
))
99 perror ("Cannot initialise SMB context");
100 smbc_free_context (*pctx
, 1);
109 static int usmb_statfs (const char *path
, struct statvfs
*vfs
)
111 if ((NULL
== path
) || (NULL
== vfs
))
114 memset (vfs
, 0, sizeof (*vfs
));
116 vfs
->f_bsize
= 32768;
117 vfs
->f_blocks
= 0x7FFFFFFFl
;
118 vfs
->f_bfree
= 0x7FFFFFFFl
;
119 vfs
->f_bavail
= 0x7FFFFFFFl
;
126 static void * usmb_init (struct fuse_conn_info
*conn
)
128 DEBUG (fputs ("usmb_init()\n", stderr
));
134 static void usmb_destroy (void *unused
)
137 DEBUG (fputs ("usmb_destroy()\n", stderr
));
141 // probably won't (can't ?) implement these:
142 // readlink mknod symlink flush fsync
144 // fuse.h says "Just a placeholder, don't set".
147 // no easy way of implementing these.
151 #define SET_ELEMENT(name,value) value
153 #define SET_ELEMENT(name,value) name = value
155 static struct fuse_operations fuse_ops
= {
156 SET_ELEMENT (.getattr
, usmb_getattr
),
157 SET_ELEMENT (.readlink
, NULL
),
158 SET_ELEMENT (.getdir
, NULL
),
159 SET_ELEMENT (.mknod
, NULL
),
160 SET_ELEMENT (.mkdir
, usmb_mkdir
),
161 SET_ELEMENT (.unlink
, usmb_unlink
),
162 SET_ELEMENT (.rmdir
, usmb_rmdir
),
163 SET_ELEMENT (.symlink
, NULL
),
164 SET_ELEMENT (.rename
, usmb_rename
),
165 SET_ELEMENT (.link
, NULL
),
166 SET_ELEMENT (.chmod
, usmb_chmod
),
167 SET_ELEMENT (.chown
, NULL
), // usmb_chown, --not implemented in libsmbclient
168 SET_ELEMENT (.truncate
, usmb_truncate
),
169 SET_ELEMENT (.utime
, usmb_utime
),
170 SET_ELEMENT (.open
, usmb_open
),
171 SET_ELEMENT (.read
, usmb_read
),
172 SET_ELEMENT (.write
, usmb_write
),
173 SET_ELEMENT (.statfs
, NULL
),
174 SET_ELEMENT (.flush
, NULL
),
175 SET_ELEMENT (.release
, usmb_release
),
176 SET_ELEMENT (.fsync
, NULL
),
177 SET_ELEMENT (.setxattr
, usmb_setxattr
),
178 SET_ELEMENT (.getxattr
, usmb_getxattr
),
179 SET_ELEMENT (.listxattr
, usmb_listxattr
),
180 SET_ELEMENT (.removexattr
, usmb_removexattr
),
181 SET_ELEMENT (.opendir
, usmb_opendir
),
182 SET_ELEMENT (.readdir
, usmb_readdir
),
183 SET_ELEMENT (.releasedir
, usmb_releasedir
),
184 SET_ELEMENT (.fsyncdir
, NULL
),
185 SET_ELEMENT (.init
, usmb_init
),
186 SET_ELEMENT (.destroy
, usmb_destroy
),
187 SET_ELEMENT (.access
, NULL
),
188 SET_ELEMENT (.create
, usmb_create
),
189 SET_ELEMENT (.ftruncate
, NULL
),
190 SET_ELEMENT (.fgetattr
, usmb_fgetattr
),
191 SET_ELEMENT (.lock
, NULL
), // TODO: implement
192 SET_ELEMENT (.utimens
, NULL
), // TODO: implement
193 SET_ELEMENT (.bmap
, NULL
), // TODO: implement
197 // this should really open() the file and check the fd, but the XML parser
198 // takes a filename, not a file descriptor
199 static bool check_conf_perms (const char *conffile
)
202 if (0 == stat (conffile
, &buf
))
204 if (getuid() != buf
.st_uid
)
206 fprintf (stderr
, "You do not own the configuration file %s\n",
211 if (buf
.st_mode
& (S_IRWXG
| S_IRWXO
))
213 fprintf (stderr
, "Configuration file %s is accessible to non-owner\n",
220 fprintf (stderr
, "Cannot stat configuration file %s: %s\n",
221 conffile
, strerror (errno
));
229 static bool create_share_name (const char *server
, const char *sharename
)
231 size_t len
= strlen ("smb:///") +
233 strlen (sharename
) + 1;
235 if (NULL
== (share
= malloc (len
)))
237 perror ("Cannot allocate share name");
241 snprintf (share
, len
, "smb://%s/%s", server
, sharename
);
242 DEBUG (fprintf (stderr
, "Share URL: %s\n", share
));
247 static void free_strings (char *sharename
)
260 int main (int argc
, char **argv
)
262 const char *conffile
, *mountid
;
263 char *sharename
= NULL
;
266 static char conf
[256];
267 snprintf (conf
, sizeof (conf
), "%s/.usmb.conf", getenv ("HOME"));
271 if (!parse_args (&argc
, &argv
, &mountid
, &conffile
))
274 if (!check_conf_perms (conffile
) ||
275 !conffile_get_mount (conffile
, mountid
,
276 &server
, &sharename
, &mountpoint
, &options
,
277 &domain
, &username
, &password
))
280 if (!create_share_name (server
, sharename
) ||
281 !create_smb_context (domain
, username
, &ctx
))
283 free_strings (sharename
);
287 DEBUG (fprintf (stderr
, "Username: %s\\%s\n", domain
, username
));
292 build_fuse_args (options
, mountpoint
, &fuse_argc
, &fuse_argv
);
293 int ret
= fuse_main (fuse_argc
, fuse_argv
, &fuse_ops
, NULL
);
295 smbc_free_context (ctx
, 1);
296 free_strings (sharename
);