6 * Name: smb_abstraction.c
7 * Description: Smb abstraction layer.
8 * Author: Christian Starkjohann <cs -at- hal -dot- kph -dot- tuwien -dot- ac -dot- at>
12 * Modified for use with AmigaOS by Olaf Barthel <obarthel -at- gmx -dot- net>
17 /*****************************************************************************/
19 #include <smb/smb_fs.h>
21 #include <smb/smbno.h>
23 #ifndef MAXHOSTNAMELEN
24 #define MAXHOSTNAMELEN 256
27 /*****************************************************************************/
29 #define ATTR_CACHE_TIME 5 /* cache attributes for this time */
30 #define DIR_CACHE_TIME 5 /* cache directories for this time */
31 #define DIRCACHE_SIZE 170
32 #define DOS_PATHSEP '\\'
34 /*****************************************************************************/
36 typedef struct dircache
40 int eof
; /* cache end is eof */
41 long created_at
; /* for invalidation */
42 struct smba_file
*cache_for
; /* owner of this cache */
44 struct smb_dirent cache
[1];
47 /* opaque structures for server and files: */
50 struct smb_server server
;
51 struct MinList open_files
;
52 dircache_t
* dircache
;
53 unsigned supports_E
:1;
54 unsigned supports_E_known
:1;
60 struct smba_server
*server
;
61 struct smb_dirent dirent
;
62 long attr_time
; /* time when dirent was read */
63 dircache_t
*dircache
; /* content cache for directories */
64 unsigned attr_dirty
:1; /* attribute cache is dirty */
65 unsigned is_valid
:1; /* server was down, entry removed, ... */
68 /*****************************************************************************/
70 #include "smb_abstraction.h"
72 /*****************************************************************************/
74 static int smba_connect(smba_connect_parameters_t
*p
, unsigned int ip_addr
, int use_E
, char *workgroup_name
,
75 int cache_size
, int max_transmit
, int opt_raw_smb
, smba_server_t
**result
);
76 static INLINE
int make_open(smba_file_t
*f
, int need_fid
);
77 static int write_attr(smba_file_t
*f
);
78 static void invalidate_dircache(struct smba_server
*server
, char *path
);
79 static void close_path(smba_server_t
*s
, char *path
);
80 static void smba_cleanup_dircache(struct smba_server
*server
);
81 static int smba_setup_dircache(struct smba_server
*server
, int cache_size
);
82 static int extract_service (char *service
, char *server
, size_t server_size
, char *share
, size_t share_size
);
84 /*****************************************************************************/
87 smba_connect (smba_connect_parameters_t
* p
, unsigned int ip_addr
, int use_E
, char * workgroup_name
,
88 int cache_size
, int max_transmit
, int opt_raw_smb
, smba_server_t
** result
)
91 struct smb_mount_data data
;
93 char hostname
[MAXHOSTNAMELEN
], *s
;
94 struct servent
* servent
;
98 res
= malloc (sizeof(*res
));
101 ReportError("Not enough memory.");
106 memset (res
, 0, sizeof(*res
));
107 memset (&data
, 0, sizeof (data
));
108 memset (hostname
, 0, sizeof (hostname
));
110 /* Olaf (2012-12-10): force raw SMB over TCP rather than NetBIOS. */
112 res
->server
.raw_smb
= 1;
114 errnum
= smba_setup_dircache (res
,cache_size
);
117 ReportError("Directory cache initialization failed (%ld, %s).",-errnum
,amitcp_strerror(-errnum
));
121 strlcpy(data
.workgroup_name
,workgroup_name
,sizeof(data
.workgroup_name
));
123 res
->server
.abstraction
= res
;
125 gethostname (hostname
, MAXHOSTNAMELEN
);
127 if ((s
= strchr (hostname
, '.')) != NULL
)
130 data
.addr
.sin_family
= AF_INET
;
131 data
.addr
.sin_addr
.s_addr
= ip_addr
;
133 if(res
->server
.raw_smb
)
135 servent
= getservbyname("microsoft-ds","tcp");
137 data
.addr
.sin_port
= servent
->s_port
;
139 data
.addr
.sin_port
= htons (445);
143 servent
= getservbyname("netbios-ssn","tcp");
145 data
.addr
.sin_port
= servent
->s_port
;
147 data
.addr
.sin_port
= htons (139);
150 data
.fd
= socket (AF_INET
, SOCK_STREAM
, 0);
154 ReportError("socket() call failed (%ld, %s).", errno
, amitcp_strerror (errno
));
158 strlcpy (data
.service
, p
->service
, sizeof(data
.service
));
159 StringToUpper (data
.service
);
160 strlcpy (data
.username
, p
->username
, sizeof(data
.username
));
161 strlcpy (data
.password
, p
->password
, sizeof(data
.password
));
163 /* Minimum receive buffer size is 8000 bytes, and the
164 * maximum transmit buffer size should be of the same
167 if (0 < max_transmit
&& max_transmit
< 8000)
170 if (0 < max_transmit
&& max_transmit
< 65535)
171 data
.given_max_xmit
= max_transmit
;
173 data
.given_max_xmit
= 65534; /* 2014/10/4 fm: use 65534 since some NASs report -1 but return max of 65534 bytes */
175 strlcpy (data
.server_name
, p
->server_name
, sizeof(data
.server_name
));
176 strlcpy (data
.client_name
, p
->client_name
, sizeof(data
.client_name
));
178 if (data
.server_name
[0] == '\0')
180 if (strlen (p
->server_ipname
) > 16)
182 errnum
= -ENAMETOOLONG
;
183 ReportError("Server name '%s' is too long for NetBIOS (max %ld characters).",p
->server_ipname
,16);
187 strlcpy (data
.server_name
, p
->server_ipname
, sizeof(data
.server_name
));
190 StringToUpper (data
.server_name
);
192 if (data
.client_name
[0] == '\0')
194 if (strlen (hostname
) > 16)
196 errnum
= -ENAMETOOLONG
;
197 ReportError("Local host name '%s' is too long for NetBIOS (max %ld characters).", hostname
, 16);
201 strlcpy (data
.client_name
, hostname
, sizeof(data
.client_name
));
202 StringToUpper (data
.client_name
);
205 res
->server
.mount_data
= data
;
207 NewList((struct List
*)&res
->open_files
);
209 if ((errnum
= smb_proc_connect (&res
->server
)) < 0)
211 ReportError("Cannot connect to server (%ld, %s).", -errnum
,amitcp_strerror(-errnum
));
216 res
->supports_E_known
= 1;
227 smba_cleanup_dircache (res
);
234 /*****************************************************************************/
237 smba_disconnect (smba_server_t
* server
)
239 CloseSocket (server
->server
.mount_data
.fd
);
241 smba_cleanup_dircache(server
);
246 /*****************************************************************************/
249 make_open (smba_file_t
* f
, int need_fid
)
254 if (!f
->is_valid
|| (need_fid
&& !f
->dirent
.opened
))
258 if (!f
->is_valid
|| f
->attr_time
== -1 || GetCurrentTime() - f
->attr_time
> ATTR_CACHE_TIME
)
260 errnum
= smb_proc_getattr_core (&s
->server
, f
->dirent
.complete_path
, f
->dirent
.len
, &f
->dirent
);
265 if ((f
->dirent
.attr
& aDIR
) == 0) /* a regular file */
267 if (need_fid
|| !s
->supports_E_known
|| s
->supports_E
)
269 LOG (("opening file %s\n", f
->dirent
.complete_path
));
270 errnum
= smb_proc_open (&s
->server
, f
->dirent
.complete_path
, f
->dirent
.len
, &f
->dirent
);
274 if (s
->supports_E
|| !s
->supports_E_known
)
276 if (smb_proc_getattrE (&s
->server
, &f
->dirent
) < 0)
278 if (!s
->supports_E_known
)
280 s
->supports_E_known
= 1;
282 } /* ignore errors here */
286 s
->supports_E_known
= 1;
294 /* don't open directory, initialize directory cache */
295 if (f
->dircache
!= NULL
)
297 f
->dircache
->cache_for
= NULL
;
298 f
->dircache
->len
= 0;
303 f
->attr_time
= GetCurrentTime();
314 /*****************************************************************************/
317 smba_open (smba_server_t
* s
, char *name
, size_t name_size
, smba_file_t
** file
)
324 f
= malloc (sizeof(*f
));
331 memset(f
,0,sizeof(*f
));
333 f
->dirent
.complete_path
= name
;
334 f
->dirent
.complete_path_size
= name_size
;
335 f
->dirent
.len
= strlen (name
);
338 errnum
= make_open (f
, 0);
342 AddTail ((struct List
*)&s
->open_files
, (struct Node
*)f
);
357 /*****************************************************************************/
360 write_attr (smba_file_t
* f
)
364 LOG (("file %s\n", f
->dirent
.complete_path
));
366 errnum
= make_open (f
, 0);
370 if (f
->dirent
.opened
&& f
->server
->supports_E
)
371 errnum
= smb_proc_setattrE (&f
->server
->server
, f
->dirent
.fileid
, &f
->dirent
);
373 errnum
= smb_proc_setattr_core (&f
->server
->server
, f
->dirent
.complete_path
, f
->dirent
.len
, &f
->dirent
);
390 /*****************************************************************************/
393 smba_close (smba_file_t
* f
)
397 if(f
->node
.mln_Succ
!= NULL
|| f
->node
.mln_Pred
!= NULL
)
398 Remove((struct Node
*)f
);
403 if (f
->dirent
.opened
)
405 LOG (("closing file %s\n", f
->dirent
.complete_path
));
406 smb_proc_close (&f
->server
->server
, f
->dirent
.fileid
, f
->dirent
.mtime
);
409 if (f
->dircache
!= NULL
)
411 f
->dircache
->cache_for
= NULL
;
412 f
->dircache
->len
= 0;
420 /*****************************************************************************/
423 smba_read (smba_file_t
* f
, char *data
, long len
, long offset
)
425 int num_bytes_read
= 0;
426 int maxsize
, count
, result
;
429 errnum
= make_open (f
, 1);
436 D(("read %ld bytes from offset %ld",len
,offset
));
438 /* SMB_COM_READ_RAW and SMB_COM_WRITE_RAW supported? */
439 if (f
->server
->server
.capabilities
& CAP_RAW_MODE
)
441 SHOWVALUE(f
->server
->server
.max_buffer_size
);
443 if(len
<= f
->server
->server
.max_raw_size
)
445 result
= smb_proc_read_raw (&f
->server
->server
, &f
->dirent
, offset
, len
, data
);
448 num_bytes_read
+= result
;
452 LOG (("smb_proc_read_raw(%s)->%ld\n", f
->dirent
.complete_path
, result
));
460 n
= min(len
,f
->server
->server
.max_raw_size
);
462 result
= smb_proc_read_raw (&f
->server
->server
, &f
->dirent
, offset
, n
, data
);
465 D(("!!! wanted to read %ld bytes, got %ld",n
,result
));
469 num_bytes_read
+= result
;
476 D(("read returned fewer characters than expected (%ld < %ld)",result
,n
));
485 /* Nothing read so far. */
489 /* Raw read not supported and no data read yet?
490 * Fall back onto SMB_COM_READ.
492 if (result
<= 0 && num_bytes_read
== 0)
494 maxsize
= f
->server
->server
.max_buffer_size
- SMB_HEADER_LEN
- 5 * 2 - 5;
498 count
= min(len
,maxsize
);
500 result
= smb_proc_read (&f
->server
->server
, &f
->dirent
, offset
, count
, data
, 0);
504 num_bytes_read
+= result
;
511 D(("read returned fewer characters than expected (%ld < %ld)",result
,count
));
522 result
= num_bytes_read
;
529 /*****************************************************************************/
532 smba_write (smba_file_t
* f
, char *data
, long len
, long offset
)
534 int maxsize
, count
, result
;
535 long num_bytes_written
= 0;
538 errnum
= make_open (f
, 1);
545 /* Calculate maximum number of bytes that could be transferred with
546 a single SMBwrite packet... */
547 maxsize
= f
->server
->server
.max_buffer_size
- (SMB_HEADER_LEN
+ 5 * sizeof (word
) + 5) - 4;
551 /* Use a single SMBwrite packet whenever possible instead of a SMBwritebraw
552 because that requires two packets to be sent. */
553 result
= smb_proc_write (&f
->server
->server
, &f
->dirent
, offset
, len
, data
);
557 num_bytes_written
+= result
;
562 /* Nothing was written yet. */
565 if (f
->server
->server
.capabilities
& CAP_RAW_MODE
)
570 /* Try to send the maximum number of bytes with the two SMBwritebraw packets. */
571 max_xmit
= 2 * f
->server
->server
.max_buffer_size
- (SMB_HEADER_LEN
+ 12 * sizeof (word
) + 4) - 8;
573 /* If the number of bytes that should be transferred exceed the number of
574 bytes that could be transferred by a single call to smb_proc_write_raw,
575 the data is transfered as before: Only by the second packet. This
576 prevents the CPU from copying the data into the transferbuffer. */
578 max_xmit
= f
->server
->server
.max_buffer_size
- 4;
582 n
= min(len
,max_xmit
);
586 /* Use a single SMBwrite packet whenever possible instead of a
587 * SMBwritebraw because that requires two packets to be sent.
589 result
= smb_proc_write (&f
->server
->server
, &f
->dirent
, offset
, n
, data
);
593 result
= smb_proc_write_raw (&f
->server
->server
, &f
->dirent
, offset
, n
, data
);
596 /* Stop if the write operation failed. We'll try again with
597 * SMB_COM_WRITE if possible.
605 num_bytes_written
+= result
;
607 /* Fewer data written than intended? Could be out of disk space. */
614 /* Raw write failed and no data has been written yet?
615 * Fall back onto SMB_COM_WRITE.
617 if (result
<= 0 && num_bytes_written
== 0)
621 count
= min(len
,maxsize
);
623 result
= smb_proc_write (&f
->server
->server
, &f
->dirent
, offset
, count
, data
);
630 num_bytes_written
+= result
;
632 /* Fewer data written than intended? Could be out of disk space. */
644 result
= num_bytes_written
;
651 f
->dirent
.mtime
= GetCurrentTime();
653 /* Even if one write access failed, we may have succeeded
654 * at writing some data. Hence we update the cached file
657 if (offset
+ num_bytes_written
> f
->dirent
.size
)
658 f
->dirent
.size
= offset
+ num_bytes_written
;
663 /*****************************************************************************/
666 smba_seek (smba_file_t
*f
, long offset
, long mode
, off_t
* new_position_ptr
)
671 D(("seek %ld bytes from position %s",offset
,mode
> 0 ? (mode
== 2 ? "SEEK_END" : "SEEK_CUR") : "SEEK_SET"));
673 errnum
= make_open (f
, 1);
680 errnum
= smb_proc_lseek (&f
->server
->server
, &f
->dirent
, offset
, mode
, new_position_ptr
);
694 /*****************************************************************************/
696 /* perform a single record-lock */
698 smba_lockrec (smba_file_t
*f
, long offset
, long len
, long mode
, int unlocked
, long timeout
)
700 struct smb_lkrng
*rec_lock
= NULL
;
704 errnum
= make_open (f
, 1);
714 rec_lock
= malloc (sizeof (*rec_lock
));
715 if (rec_lock
== NULL
)
721 rec_lock
->offset
= offset
,
724 errnum
= smb_proc_lockingX (&f
->server
->server
, &f
->dirent
, rec_lock
, 1, mode
, timeout
);
741 /*****************************************************************************/
744 smba_getattr (smba_file_t
* f
, smba_stat_t
* data
)
746 long now
= GetCurrentTime();
750 errnum
= make_open (f
, 0);
757 if (f
->attr_time
== -1 || (now
- f
->attr_time
) > ATTR_CACHE_TIME
)
759 LOG (("file %s\n", f
->dirent
.complete_path
));
761 if (f
->dirent
.opened
&& f
->server
->supports_E
)
762 errnum
= smb_proc_getattrE (&f
->server
->server
, &f
->dirent
);
764 errnum
= smb_proc_getattr_core (&f
->server
->server
, f
->dirent
.complete_path
, f
->dirent
.len
, &f
->dirent
);
775 data
->is_dir
= (f
->dirent
.attr
& aDIR
) != 0;
776 data
->is_wp
= (f
->dirent
.attr
& aRONLY
) != 0;
777 data
->is_hidden
= (f
->dirent
.attr
& aHIDDEN
) != 0;
778 data
->is_system
= (f
->dirent
.attr
& aSYSTEM
) != 0;
779 data
->is_archive
= (f
->dirent
.attr
& aARCH
) != 0;
781 data
->size
= f
->dirent
.size
;
782 data
->atime
= f
->dirent
.atime
;
783 data
->ctime
= f
->dirent
.ctime
;
784 data
->mtime
= f
->dirent
.mtime
;
793 /*****************************************************************************/
796 smba_setattr (smba_file_t
* f
, smba_stat_t
* data
)
801 if (data
->atime
!= -1)
802 f
->dirent
.atime
= data
->atime
;
804 if (data
->ctime
!= -1)
805 f
->dirent
.ctime
= data
->ctime
;
807 if (data
->mtime
!= -1)
808 f
->dirent
.mtime
= data
->mtime
;
811 f
->dirent
.attr
|= aRONLY
;
813 f
->dirent
.attr
&= ~aRONLY
;
815 if (data
->is_archive
)
816 f
->dirent
.attr
|= aARCH
;
818 f
->dirent
.attr
&= ~aARCH
;
821 f
->dirent
.attr
|= aSYSTEM
;
823 f
->dirent
.attr
&= ~aSYSTEM
;
827 errnum
= write_attr (f
);
834 if (data
->size
!= -1 && data
->size
!= (int)f
->dirent
.size
)
836 errnum
= make_open (f
, 1);
843 errnum
= smb_proc_trunc (&f
->server
->server
, f
->dirent
.fileid
, data
->size
);
850 f
->dirent
.size
= data
->size
;
860 /*****************************************************************************/
863 smba_readdir (smba_file_t
* f
, long offs
, void *d
, smba_callback_t callback
)
865 int cache_index
, o
, eof
, count
= 0;
866 long now
= GetCurrentTime();
872 errnum
= make_open (f
, 0);
879 if (f
->dircache
== NULL
) /* get a cache */
881 dircache_t
* dircache
= f
->server
->dircache
;
883 if (dircache
->cache_for
!= NULL
)
884 dircache
->cache_for
->dircache
= NULL
; /* steal it */
886 dircache
->eof
= dircache
->len
= dircache
->base
= 0;
887 dircache
->cache_for
= f
;
889 f
->dircache
= dircache
;
891 LOG (("stealing cache\n"));
895 if ((now
- f
->dircache
->created_at
) >= DIR_CACHE_TIME
)
897 f
->dircache
->eof
= f
->dircache
->len
= f
->dircache
->base
= 0;
899 LOG (("cache outdated\n"));
903 for (cache_index
= offs
; ; cache_index
++)
905 if (cache_index
< f
->dircache
->base
/* fill cache if necessary */
906 || cache_index
>= f
->dircache
->base
+ f
->dircache
->len
)
908 if (cache_index
>= f
->dircache
->base
+ f
->dircache
->len
&& f
->dircache
->eof
)
909 break; /* nothing more to read */
911 LOG (("cachefill for %s\n", f
->dirent
.complete_path
));
912 LOG (("\tbase was: %ld, len was: %ld, newbase=%ld\n", f
->dircache
->base
, f
->dircache
->len
, cache_index
));
914 f
->dircache
->len
= 0;
915 f
->dircache
->base
= cache_index
;
917 num_entries
= smb_proc_readdir (&f
->server
->server
, f
->dirent
.complete_path
, cache_index
, f
->dircache
->cache_size
, f
->dircache
->cache
);
920 result
= num_entries
;
924 /* Avoid some hits if restart/retry occured. Should fix the real root
925 of this problem really, but I am not bored enough atm. -Piru
926 ZZZ this needs further investigation. */
927 if (f
->dircache
== NULL
)
929 LOG (("lost dircache due to an error, bailing out!\n"));
934 f
->dircache
->len
= num_entries
;
935 f
->dircache
->eof
= (num_entries
< f
->dircache
->cache_size
);
936 f
->dircache
->created_at
= now
;
938 LOG (("cachefill with %ld entries\n", num_entries
));
941 o
= cache_index
- f
->dircache
->base
;
942 eof
= (o
>= (f
->dircache
->len
- 1) && f
->dircache
->eof
);
945 LOG (("delivering '%s', cache_index=%ld, eof=%ld\n", f
->dircache
->cache
[o
].complete_path
, cache_index
, eof
));
947 data
.is_dir
= (f
->dircache
->cache
[o
].attr
& aDIR
) != 0;
948 data
.is_wp
= (f
->dircache
->cache
[o
].attr
& aRONLY
) != 0;
949 data
.is_hidden
= (f
->dircache
->cache
[o
].attr
& aHIDDEN
) != 0;
950 data
.is_system
= (f
->dircache
->cache
[o
].attr
& aSYSTEM
) != 0;
951 data
.is_archive
= (f
->dircache
->cache
[o
].attr
& aARCH
) != 0;
952 data
.size
= f
->dircache
->cache
[o
].size
;
953 data
.atime
= f
->dircache
->cache
[o
].atime
;
954 data
.ctime
= f
->dircache
->cache
[o
].ctime
;
955 data
.mtime
= f
->dircache
->cache
[o
].mtime
;
957 if ((*callback
) (d
, cache_index
, cache_index
+ 1, f
->dircache
->cache
[o
].complete_path
, eof
, &data
))
968 /*****************************************************************************/
971 invalidate_dircache (struct smba_server
* server
, char * path
)
973 dircache_t
* dircache
= server
->dircache
;
974 char other_path
[SMB_MAXNAMELEN
+ 1];
982 strlcpy(other_path
,path
,sizeof(other_path
));
984 len
= strlen(other_path
);
985 for(i
= len
-1 ; i
>= 0 ; i
--)
989 other_path
[0] = DOS_PATHSEP
;
990 other_path
[1] = '\0';
992 else if (other_path
[i
] == DOS_PATHSEP
)
994 other_path
[i
] = '\0';
1001 other_path
[0] = '\0';
1004 SHOWSTRING(other_path
);
1006 if(dircache
->cache_for
!= NULL
)
1007 SHOWSTRING(dircache
->cache_for
->dirent
.complete_path
);
1009 SHOWMSG("-- directory cache is empty --");
1011 if(path
== NULL
|| (dircache
->cache_for
!= NULL
&& CompareNames(other_path
,dircache
->cache_for
->dirent
.complete_path
) == SAME
))
1013 SHOWMSG("clearing directory cache");
1015 dircache
->eof
= dircache
->len
= dircache
->base
= 0;
1016 if(dircache
->cache_for
!= NULL
)
1018 dircache
->cache_for
->dircache
= NULL
;
1019 dircache
->cache_for
= NULL
;
1026 /*****************************************************************************/
1029 smba_create (smba_file_t
* dir
, const char *name
, smba_stat_t
* attr
)
1031 struct smb_dirent entry
;
1036 errnum
= make_open (dir
, 0);
1043 memset (&entry
, 0, sizeof (entry
));
1046 entry
.attr
|= aRONLY
;
1048 if (attr
->is_archive
)
1049 entry
.attr
|= aARCH
;
1051 if (attr
->is_system
)
1052 entry
.attr
|= aSYSTEM
;
1054 entry
.atime
= entry
.mtime
= entry
.ctime
= GetCurrentTime();
1056 path
= malloc (strlen (name
) + dir
->dirent
.len
+ 2);
1063 memcpy (path
, dir
->dirent
.complete_path
, dir
->dirent
.len
);
1064 path
[dir
->dirent
.len
] = DOS_PATHSEP
;
1065 strcpy (&path
[dir
->dirent
.len
+ 1], name
);
1067 errnum
= smb_proc_create (&dir
->server
->server
, path
, strlen (path
), &entry
);
1074 invalidate_dircache (dir
->server
, path
);
1086 /*****************************************************************************/
1089 smba_mkdir (smba_file_t
* dir
, const char *name
)
1095 errnum
= make_open (dir
, 0);
1102 path
= malloc (strlen (name
) + dir
->dirent
.len
+ 2);
1109 memcpy (path
, dir
->dirent
.complete_path
, dir
->dirent
.len
);
1110 path
[dir
->dirent
.len
] = DOS_PATHSEP
;
1111 strcpy (&path
[dir
->dirent
.len
+ 1], name
);
1113 errnum
= smb_proc_mkdir (&dir
->server
->server
, path
, strlen (path
));
1120 invalidate_dircache (dir
->server
, path
);
1132 /*****************************************************************************/
1135 close_path (smba_server_t
* s
, char *path
)
1139 for (p
= (smba_file_t
*)s
->open_files
.mlh_Head
;
1140 p
->node
.mln_Succ
!= NULL
;
1141 p
= (smba_file_t
*)p
->node
.mln_Succ
)
1143 if (p
->is_valid
&& CompareNames(p
->dirent
.complete_path
, path
) == SAME
)
1145 if (p
->dirent
.opened
)
1146 smb_proc_close (&s
->server
, p
->dirent
.fileid
, p
->dirent
.mtime
);
1148 p
->dirent
.opened
= 0;
1154 /*****************************************************************************/
1157 smba_remove (smba_server_t
* s
, char *path
)
1162 close_path (s
, path
);
1164 errnum
= smb_proc_unlink (&s
->server
, path
, strlen (path
));
1171 invalidate_dircache (s
, path
);
1180 /*****************************************************************************/
1183 smba_rmdir (smba_server_t
* s
, char *path
)
1188 close_path (s
, path
);
1190 errnum
= smb_proc_rmdir (&s
->server
, path
, strlen (path
));
1197 invalidate_dircache (s
, path
);
1206 /*****************************************************************************/
1209 smba_rename (smba_server_t
* s
, char *from
, char *to
)
1214 close_path (s
, from
);
1216 errnum
= smb_proc_mv (&s
->server
, from
, strlen (from
), to
, strlen (to
));
1223 invalidate_dircache (s
, from
);
1232 /*****************************************************************************/
1235 smba_statfs (smba_server_t
* s
, long *bsize
, long *blocks
, long *bfree
)
1237 struct smb_dskattr dskattr
;
1241 errnum
= smb_proc_dskattr (&s
->server
, &dskattr
);
1248 (*bsize
) = dskattr
.blocksize
* dskattr
.allocblocks
;
1249 (*blocks
) = dskattr
.total
;
1250 (*bfree
) = dskattr
.free
;
1259 /*****************************************************************************/
1262 smb_invalidate_all_inodes (struct smb_server
*server
)
1266 invalidate_dircache (server
->abstraction
, NULL
);
1268 for (f
= (smba_file_t
*)server
->abstraction
->open_files
.mlh_Head
;
1269 f
->node
.mln_Succ
!= NULL
;
1270 f
= (smba_file_t
*)f
->node
.mln_Succ
)
1272 f
->dirent
.opened
= 0;
1277 /*****************************************************************************/
1280 free_dircache(dircache_t
* the_dircache
)
1284 for (i
= 0; i
< the_dircache
->cache_size
; i
++)
1286 if(the_dircache
->cache
[i
].complete_path
!= NULL
)
1287 free(the_dircache
->cache
[i
].complete_path
);
1294 smba_cleanup_dircache(struct smba_server
* server
)
1296 dircache_t
* the_dircache
;
1298 the_dircache
= server
->dircache
;
1299 if(the_dircache
!= NULL
)
1301 free_dircache(the_dircache
);
1302 server
->dircache
= NULL
;
1307 smba_setup_dircache (struct smba_server
* server
,int cache_size
)
1309 dircache_t
* the_dircache
;
1310 int error
= -ENOMEM
;
1313 the_dircache
= malloc(sizeof(*the_dircache
) + (cache_size
-1) * sizeof(the_dircache
->cache
));
1314 if(the_dircache
== NULL
)
1317 memset(the_dircache
,0,sizeof(*the_dircache
));
1318 the_dircache
->cache_size
= cache_size
;
1320 for (i
= 0; i
< the_dircache
->cache_size
; i
++)
1322 the_dircache
->cache
[i
].complete_path
= malloc (SMB_MAXNAMELEN
+ 1);
1323 if(the_dircache
->cache
[i
].complete_path
== NULL
)
1326 the_dircache
->cache
[i
].complete_path_size
= SMB_MAXNAMELEN
+ 1;
1329 server
->dircache
= the_dircache
;
1330 the_dircache
= NULL
;
1336 if(the_dircache
!= NULL
)
1337 free_dircache(the_dircache
);
1342 /*****************************************************************************/
1345 extract_service (char *service
, char *server
, size_t server_size
, char *share
, size_t share_size
)
1349 char * complete_service
;
1350 char * service_copy
;
1353 service_copy
= malloc(strlen(service
)+1);
1354 if(service_copy
== NULL
)
1357 ReportError("Not enough memory.");
1361 strcpy (service_copy
, service
);
1362 complete_service
= service_copy
;
1364 if (strlen (complete_service
) < 4 || complete_service
[0] != '/')
1367 ReportError("Invalid service name '%s'.",complete_service
);
1371 while (complete_service
[0] == '/')
1372 complete_service
+= 1;
1374 share_start
= strchr (complete_service
, '/');
1375 if (share_start
== NULL
)
1378 ReportError("Invalid share name '%s'.",complete_service
);
1382 (*share_start
++) = '\0';
1383 root_start
= strchr (share_start
, '/');
1385 if (root_start
!= NULL
)
1386 (*root_start
) = '\0';
1388 if ((strlen (complete_service
) > 63) || (strlen (share_start
) > 63))
1390 result
= -ENAMETOOLONG
;
1391 ReportError("Server or share name is too long in '%s' (max %ld characters).",service
,63);
1395 strlcpy (server
, complete_service
, server_size
);
1396 strlcpy (share
, share_start
, share_size
);
1400 if(service_copy
!= NULL
)
1407 smba_start(char * service
,char *opt_workgroup
,char *opt_username
,char *opt_password
,char *opt_clientname
,
1408 char *opt_servername
,int opt_cachesize
,int opt_max_transmit
,int opt_raw_smb
,smba_server_t
** result
)
1410 smba_connect_parameters_t par
;
1411 smba_server_t
*the_server
= NULL
;
1414 int use_extended
= 0;
1415 char server_name
[17], client_name
[17];
1416 char username
[64], password
[64];
1418 char server
[64], share
[64];
1419 unsigned int ipAddr
;
1423 (*username
) = (*password
) = (*server_name
) = (*client_name
) = '\0';
1425 error
= extract_service (service
, server
, sizeof(server
), share
, sizeof(share
));
1429 ipAddr
= inet_addr (server
);
1430 if (ipAddr
== INADDR_NONE
) /* name was given, not numeric */
1434 h
= gethostbyname (server
);
1435 lookup_error
= h_errno
;
1439 ipAddr
= ((struct in_addr
*)(h
->h_addr
))->s_addr
;
1441 else if (BroadcastNameQuery(server
,"",(UBYTE
*)&ipAddr
) != 0)
1443 ReportError("Unknown host '%s' (%ld, %s).",server
,lookup_error
,host_strerror(lookup_error
));
1450 char hostName
[MAXHOSTNAMELEN
+1];
1452 h
= gethostbyaddr ((char *) &ipAddr
, sizeof (ipAddr
), AF_INET
);
1455 ReportError("Unknown host '%s' (%ld, %s).",server
,h_errno
,host_strerror(errno
));
1460 /* Brian Willette: Now we will set the server name to the DNS
1461 hostname, hopefully this will be the same as the NetBIOS name for
1463 We do this because the user supplied no hostname, and we
1464 need one for NetBIOS, this is the best guess choice we have
1465 NOTE: If the names are different between DNS and NetBIOS on
1466 the windows side, the user MUST use the -s option. */
1467 for (i
= 0; h
->h_name
[i
] != '.' && h
->h_name
[i
] != '\0' && i
< 255; i
++)
1468 hostName
[i
] = h
->h_name
[i
];
1472 /* Make sure the hostname is 16 characters or less (for Netbios) */
1473 if (strlen (hostName
) > 16)
1475 ReportError("Server host name '%s' is too long (max %ld characters).", hostName
, 16);
1476 error
= (-ENAMETOOLONG
);
1480 strlcpy (server_name
, hostName
, sizeof(server_name
));
1483 if(opt_password
!= NULL
)
1485 if(strlen(opt_password
) >= sizeof(password
))
1487 ReportError("Password is too long (max %ld characters).", sizeof(password
)-1);
1488 error
= (-ENAMETOOLONG
);
1492 strlcpy(password
,opt_password
,sizeof(password
));
1495 if(strlen(opt_username
) >= sizeof(username
))
1497 ReportError("User name '%s' is too long (max %ld characters).", username
,sizeof(username
)-1);
1498 error
= (-ENAMETOOLONG
);
1502 strlcpy(username
,opt_username
,sizeof(username
));
1503 StringToUpper(username
);
1505 if (strlen(opt_workgroup
) > 15)
1507 ReportError("Workgroup/domain name '%s' is too long (max %ld characters).", opt_workgroup
,15);
1508 error
= (-ENAMETOOLONG
);
1512 strlcpy (workgroup
, opt_workgroup
, sizeof(workgroup
));
1513 StringToUpper (workgroup
);
1515 if(opt_servername
!= NULL
)
1517 if (strlen (opt_servername
) > 16)
1519 ReportError("Server name '%s' is too long (max %ld characters).", opt_servername
,16);
1520 error
= (-ENAMETOOLONG
);
1524 strlcpy (server_name
, opt_servername
, sizeof(server_name
));
1527 if(opt_clientname
!= NULL
)
1529 if (strlen (opt_clientname
) > 16)
1531 ReportError("Client name '%s' is too long (max %ld characters).", opt_clientname
,16);
1532 error
= (-ENAMETOOLONG
);
1536 strlcpy (client_name
, opt_clientname
, sizeof(client_name
));
1539 if(opt_cachesize
< 1)
1540 opt_cachesize
= DIRCACHE_SIZE
;
1541 else if (opt_cachesize
< 10)
1544 strlcpy(par
.server_ipname
,server
,sizeof(par
.server_ipname
));
1545 par
.server_name
= server_name
;
1546 par
.client_name
= client_name
;
1548 strlcpy(par
.service
,share
,sizeof(par
.service
));
1549 par
.username
= username
;
1550 par
.password
= password
;
1552 error
= smba_connect (&par
, ipAddr
, use_extended
, workgroup
, opt_cachesize
, opt_max_transmit
, opt_raw_smb
, &the_server
);
1555 ReportError("Could not connect to server (%ld, %s).",-error
,amitcp_strerror(-error
));
1559 (*result
) = the_server
;
1568 /*****************************************************************************/
1571 smba_get_dircache_size(struct smba_server
* server
)
1575 result
= server
->dircache
->cache_size
;
1580 /*****************************************************************************/
1583 smba_change_dircache_size(struct smba_server
* server
,int cache_size
)
1585 dircache_t
* new_cache
;
1586 dircache_t
* old_dircache
= server
->dircache
;
1590 result
= old_dircache
->cache_size
;
1592 /* We have to have a minimum cache size. */
1596 /* Don't do anything if the cache size has not changed. */
1597 if(cache_size
== old_dircache
->cache_size
)
1600 /* Allocate a new cache and set it up with defaults. Note that
1601 * the file name pointers in the cache are still not initialized.
1603 new_cache
= malloc(sizeof(*new_cache
) + (cache_size
-1) * sizeof(new_cache
->cache
));
1604 if(new_cache
== NULL
)
1607 memset(new_cache
,0,sizeof(*new_cache
));
1608 new_cache
->cache_size
= cache_size
;
1610 /* If the new cache is to be larger than the old one, allocate additional file name slots. */
1611 if(cache_size
> old_dircache
->cache_size
)
1613 /* Initialize the file name pointers so that free_dircache()
1614 * can be called safely, if necessary.
1616 for(i
= 0 ; i
< cache_size
; i
++)
1617 new_cache
->cache
[i
].complete_path
= NULL
;
1619 /* Allocate memory for the file names. */
1620 for(i
= old_dircache
->cache_size
; i
< cache_size
; i
++)
1622 new_cache
->cache
[i
].complete_path
= malloc (SMB_MAXNAMELEN
+ 1);
1623 if(new_cache
->cache
[i
].complete_path
== NULL
)
1625 free_dircache(new_cache
);
1629 new_cache
->cache
[i
].complete_path_size
= SMB_MAXNAMELEN
+ 1;
1632 /* Reuse the file name buffers allocated for the old cache. */
1633 for(i
= 0 ; i
< old_dircache
->cache_size
; i
++)
1635 new_cache
->cache
[i
].complete_path
= old_dircache
->cache
[i
].complete_path
;
1636 new_cache
->cache
[i
].complete_path_size
= old_dircache
->cache
[i
].complete_path_size
;
1638 old_dircache
->cache
[i
].complete_path
= NULL
;
1643 /* Reuse the file name buffers allocated for the old cache. */
1644 for(i
= 0 ; i
< cache_size
; i
++)
1646 new_cache
->cache
[i
].complete_path
= old_dircache
->cache
[i
].complete_path
;
1647 new_cache
->cache
[i
].complete_path_size
= old_dircache
->cache
[i
].complete_path_size
;
1649 old_dircache
->cache
[i
].complete_path
= NULL
;
1653 invalidate_dircache(server
, NULL
);
1655 free_dircache(old_dircache
);
1657 server
->dircache
= new_cache
;
1658 result
= cache_size
;