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 #define MAXHOSTNAMELEN 256
25 /*****************************************************************************/
27 #define ATTR_CACHE_TIME 5 /* cache attributes for this time */
28 #define DIR_CACHE_TIME 5 /* cache directories for this time */
29 #define DIRCACHE_SIZE 170
30 #define DOS_PATHSEP '\\'
32 /*****************************************************************************/
34 typedef struct dircache
38 int eof
; /* cache end is eof */
39 long created_at
; /* for invalidation */
40 struct smba_file
*cache_for
; /* owner of this cache */
42 struct smb_dirent cache
[1];
45 /* opaque structures for server and files: */
48 struct smb_server server
;
49 struct MinList open_files
;
50 dircache_t
* dircache
;
51 unsigned supports_E
:1;
52 unsigned supports_E_known
:1;
58 struct smba_server
*server
;
59 struct smb_dirent dirent
;
60 long attr_time
; /* time when dirent was read */
61 dircache_t
*dircache
; /* content cache for directories */
62 unsigned attr_dirty
:1; /* attribute cache is dirty */
63 unsigned is_valid
:1; /* server was down, entry removed, ... */
66 /*****************************************************************************/
68 #include "smb_abstraction.h"
70 /*****************************************************************************/
72 static int smba_connect(smba_connect_parameters_t
*p
, unsigned int ip_addr
, int use_E
, char *workgroup_name
, int cache_size
, smba_server_t
**result
);
73 static INLINE
int make_open(smba_file_t
*f
, int need_fid
);
74 static int write_attr(smba_file_t
*f
);
75 static void invalidate_dircache(struct smba_server
*server
, char *path
);
76 static void close_path(smba_server_t
*s
, char *path
);
77 static void smba_cleanup_dircache(struct smba_server
*server
);
78 static int smba_setup_dircache(struct smba_server
*server
, int cache_size
);
79 static int extract_service (char *service
, char *server
, size_t server_size
, char *share
, size_t share_size
);
81 /*****************************************************************************/
84 smba_connect (smba_connect_parameters_t
* p
, unsigned int ip_addr
, int use_E
, char * workgroup_name
, int cache_size
, smba_server_t
** result
)
87 struct smb_mount_data data
;
89 char hostname
[MAXHOSTNAMELEN
], *s
;
90 struct servent
* servent
;
94 res
= malloc (sizeof(*res
));
97 ReportError("Not enough memory.");
102 memset (res
, 0, sizeof(*res
));
103 memset (&data
, 0, sizeof (data
));
104 memset (hostname
, 0, sizeof (hostname
));
106 errnum
= smba_setup_dircache (res
,cache_size
);
109 ReportError("Directory cache initialization failed (%ld, %s).",-errnum
,amitcp_strerror(-errnum
));
113 strlcpy(data
.workgroup_name
,workgroup_name
,sizeof(data
.workgroup_name
));
115 res
->server
.abstraction
= res
;
117 gethostname (hostname
, MAXHOSTNAMELEN
);
119 if ((s
= strchr (hostname
, '.')) != NULL
)
122 data
.addr
.sin_family
= AF_INET
;
123 data
.addr
.sin_addr
.s_addr
= ip_addr
;
125 servent
= getservbyname("netbios-ssn","tcp");
127 data
.addr
.sin_port
= htons (servent
->s_port
);
129 data
.addr
.sin_port
= htons (SMB_PORT
);
131 data
.fd
= socket (AF_INET
, SOCK_STREAM
, 0);
135 ReportError("socket() call failed (%ld, %s).", errno
, amitcp_strerror (errno
));
139 strlcpy (data
.service
, p
->service
, sizeof(data
.service
));
140 StringToUpper (data
.service
);
141 strlcpy (data
.username
, p
->username
, sizeof(data
.username
));
142 strlcpy (data
.password
, p
->password
, sizeof(data
.password
));
145 data
.max_xmit
= p
->max_xmit
;
147 data
.max_xmit
= 65530 /*8300*/;
149 strlcpy (data
.server_name
, p
->server_name
, sizeof(data
.server_name
));
150 strlcpy (data
.client_name
, p
->client_name
, sizeof(data
.client_name
));
152 if (data
.server_name
[0] == '\0')
154 if (strlen (p
->server_ipname
) > 16)
156 errnum
= -ENAMETOOLONG
;
157 ReportError("Server name '%s' is too long for NetBIOS (max %ld characters).",p
->server_ipname
,16);
161 strlcpy (data
.server_name
, p
->server_ipname
, sizeof(data
.server_name
));
164 StringToUpper (data
.server_name
);
166 if (data
.client_name
[0] == '\0')
168 if (strlen (hostname
) > 16)
170 errnum
= -ENAMETOOLONG
;
171 ReportError("Local host name '%s' is too long for NetBIOS (max %ld characters).", hostname
, 16);
175 strlcpy (data
.client_name
, hostname
, sizeof(data
.client_name
));
176 StringToUpper (data
.client_name
);
179 res
->server
.mount_data
= data
;
181 NewList((struct List
*)&res
->open_files
);
183 if ((errnum
= smb_proc_connect (&res
->server
)) < 0)
185 ReportError("Cannot connect to server (%ld, %s).", -errnum
,amitcp_strerror(-errnum
));
190 res
->supports_E_known
= 1;
200 smba_cleanup_dircache (res
);
207 /*****************************************************************************/
210 smba_disconnect (smba_server_t
* server
)
212 CloseSocket (server
->server
.mount_data
.fd
);
214 smba_cleanup_dircache(server
);
219 /*****************************************************************************/
222 make_open (smba_file_t
* f
, int need_fid
)
227 if (!f
->is_valid
|| (need_fid
&& !f
->dirent
.opened
))
231 if (!f
->is_valid
|| f
->attr_time
== -1 || GetCurrentTime() - f
->attr_time
> ATTR_CACHE_TIME
)
233 if ((errnum
= smb_proc_getattr_core (&s
->server
, f
->dirent
.complete_path
, f
->dirent
.len
, &f
->dirent
)) < 0)
237 if ((f
->dirent
.attr
& aDIR
) == 0) /* a regular file */
239 if (need_fid
|| !s
->supports_E_known
|| s
->supports_E
)
241 LOG (("opening file %s\n", f
->dirent
.complete_path
));
242 if ((errnum
= smb_proc_open (&s
->server
, f
->dirent
.complete_path
, f
->dirent
.len
, &f
->dirent
)) < 0)
245 if (s
->supports_E
|| !s
->supports_E_known
)
247 if (smb_proc_getattrE (&s
->server
, &f
->dirent
) < 0)
249 if (!s
->supports_E_known
)
251 s
->supports_E_known
= 1;
253 } /* ignore errors here */
257 s
->supports_E_known
= 1;
265 /* don't open directory, initialize directory cache */
266 if (f
->dircache
!= NULL
)
268 f
->dircache
->cache_for
= NULL
;
269 f
->dircache
->len
= 0;
274 f
->attr_time
= GetCurrentTime();
283 /*****************************************************************************/
286 smba_open (smba_server_t
* s
, char *name
, size_t name_size
, smba_file_t
** file
)
293 f
= malloc (sizeof(*f
));
300 memset(f
,0,sizeof(*f
));
302 f
->dirent
.complete_path
= name
;
303 f
->dirent
.complete_path_size
= name_size
;
304 f
->dirent
.len
= strlen (name
);
307 errnum
= make_open (f
, 0);
311 AddTail ((struct List
*)&s
->open_files
, (struct Node
*)f
);
325 /*****************************************************************************/
328 write_attr (smba_file_t
* f
)
332 LOG (("file %s\n", f
->dirent
.complete_path
));
334 errnum
= make_open (f
, 0);
338 if (f
->dirent
.opened
&& f
->server
->supports_E
)
339 errnum
= smb_proc_setattrE (&f
->server
->server
, f
->dirent
.fileid
, &f
->dirent
);
341 errnum
= smb_proc_setattr_core (&f
->server
->server
, f
->dirent
.complete_path
, f
->dirent
.len
, &f
->dirent
);
353 /*****************************************************************************/
356 smba_close (smba_file_t
* f
)
358 if(f
->node
.mln_Succ
!= NULL
|| f
->node
.mln_Pred
!= NULL
)
359 Remove((struct Node
*)f
);
364 if (f
->dirent
.opened
)
366 LOG (("closing file %s\n", f
->dirent
.complete_path
));
367 smb_proc_close (&f
->server
->server
, f
->dirent
.fileid
, f
->dirent
.mtime
);
370 if (f
->dircache
!= NULL
)
372 f
->dircache
->cache_for
= NULL
;
373 f
->dircache
->len
= 0;
380 /*****************************************************************************/
383 smba_read (smba_file_t
* f
, char *data
, long len
, long offset
)
385 int maxsize
, count
, totalcount
, result
;
389 result
= make_open (f
, 1);
393 D(("read %ld bytes from offset %ld",len
,offset
));
395 if (f
->server
->server
.blkmode
& 1)
397 SHOWVALUE(f
->server
->server
.max_xmit
);
401 result
= smb_proc_read_raw (&f
->server
->server
, &f
->dirent
, offset
, len
, data
);
403 LOG (("smb_proc_read_raw(%s)->%ld\n", f
->dirent
.complete_path
, result
));
415 result
= smb_proc_read_raw (&f
->server
->server
, &f
->dirent
, offset
, n
, data
);
418 D(("!!! wanted to read %ld bytes, got %ld",n
,result
));
426 totalcount
+= result
;
430 D(("read returned fewer characters than expected (%ld < %ld)",result
,n
));
449 maxsize
= f
->server
->server
.max_xmit
- SMB_HEADER_LEN
- 5 * 2 - 5;
453 count
= totalcount
> maxsize
? maxsize
: totalcount
;
455 result
= smb_proc_read (&f
->server
->server
, &f
->dirent
, offset
, count
, rpos
, 0);
459 bytes_read
+= result
;
460 totalcount
-= result
;
466 D(("read returned fewer characters than expected (%ld < %ld)",result
,count
));
470 while (totalcount
> 0);
481 /*****************************************************************************/
484 smba_write (smba_file_t
* f
, char *data
, long len
, long offset
)
486 int newlen
, maxsize
, totalcount
, count
, result
;
488 if ((result
= make_open (f
, 1)) < 0)
491 /* Calculate maximum number of bytes that could be tranfered with
492 a single SMBwrite packet... */
493 maxsize
= f
->server
->server
.max_xmit
- (SMB_HEADER_LEN
+ 5 * sizeof (word
) + 5) - 4;
497 /* Use a single SMBwrite packet whenever possible instead of a SMBwritebraw
498 because that requires two packets to be send. */
499 result
= smb_proc_write (&f
->server
->server
, &f
->dirent
, offset
, len
, data
);
503 /* Added by Brian Willette - We were always checking bit 2 here, but
504 according to the documentation I have, the newer versions of SMB put
505 the SMB_RAW_WRITE AND SMB_RAW_READ capability in bit 1 */
506 if ((f
->server
->server
.protocol
>= PROTOCOL_NT1
507 && f
->server
->server
.blkmode
& 1)
508 || (f
->server
->server
.protocol
< PROTOCOL_NT1
509 && f
->server
->server
.blkmode
& 2))
516 /* Try to send the maximum number of bytes with the two SMBwritebraw packets. */
517 maxxmit
= 2 * f
->server
->server
.max_xmit
- (SMB_HEADER_LEN
+ 12 * sizeof (word
) + 4) - 8;
519 /* If the number of bytes that should be transfered exceed the number of
520 bytes that could be transfered by a single call to smb_proc_write_raw,
521 the data is transfered as before: Only by the second packet, this
522 prevents the CPU from copying the data into the transferbuffer. */
524 maxxmit
= f
->server
->server
.max_xmit
- 4;
528 n
= min(len
,maxxmit
);
532 /* Use a single SMBwrite packet whenever possible instead of a
533 SMBwritebraw because that requires two packets to be send. */
534 result
= smb_proc_write (&f
->server
->server
, &f
->dirent
, offset
, n
, data
);
538 result
= smb_proc_write_raw (&f
->server
->server
, &f
->dirent
, offset
, n
, data
);
550 totalcount
+= result
;
565 /* Failed to use the SMBwritebraw packet, fallback to SMBwrite... */
571 count
= totalcount
> maxsize
? maxsize
: totalcount
;
572 result
= smb_proc_write (&f
->server
->server
, &f
->dirent
, offset
, count
, data
);
576 totalcount
-= result
;
584 while (totalcount
> 0);
596 f
->dirent
.mtime
= GetCurrentTime();
598 newlen
= f
->dirent
.size
;
600 if (offset
+ len
> newlen
)
601 newlen
= offset
+ len
;
603 f
->dirent
.size
= newlen
;
607 /*****************************************************************************/
610 smba_seek (smba_file_t
*f
, long offset
, long mode
, off_t
* new_position_ptr
)
614 D(("seek %ld bytes from position %s",offset
,mode
> 0 ? (mode
== 2 ? "SEEK_END" : "SEEK_CUR") : "SEEK_SET"));
616 if ((result
= make_open (f
, 1)) >= 0)
617 result
= smb_proc_lseek (&f
->server
->server
, &f
->dirent
, offset
, mode
, new_position_ptr
);
622 /*****************************************************************************/
624 /* perform a single record-lock */
626 smba_lockrec (smba_file_t
*f
, long offset
, long len
, long mode
, int unlocked
, long timeout
)
629 struct smb_lkrng
*rec_lock
;
631 if ((errnum
= make_open (f
, 1)) >= 0)
636 rec_lock
= malloc (sizeof (struct smb_lkrng
));
637 if (rec_lock
!= NULL
)
639 rec_lock
->offset
= offset
,
642 errnum
= smb_proc_lockingX (&f
->server
->server
, &f
->dirent
, rec_lock
, 1, mode
, timeout
);
655 /*****************************************************************************/
658 smba_getattr (smba_file_t
* f
, smba_stat_t
* data
)
660 long now
= GetCurrentTime();
663 errnum
= make_open (f
, 0);
667 if (f
->attr_time
== -1 || (now
- f
->attr_time
) > ATTR_CACHE_TIME
)
669 LOG (("file %s\n", f
->dirent
.complete_path
));
671 if (f
->dirent
.opened
&& f
->server
->supports_E
)
672 errnum
= smb_proc_getattrE (&f
->server
->server
, &f
->dirent
);
674 errnum
= smb_proc_getattr_core (&f
->server
->server
, f
->dirent
.complete_path
, f
->dirent
.len
, &f
->dirent
);
680 data
->is_dir
= (f
->dirent
.attr
& aDIR
) != 0;
681 data
->is_wp
= (f
->dirent
.attr
& aRONLY
) != 0;
682 data
->is_hidden
= (f
->dirent
.attr
& aHIDDEN
) != 0;
683 data
->is_system
= (f
->dirent
.attr
& aSYSTEM
) != 0;
684 data
->is_archive
= (f
->dirent
.attr
& aARCH
) != 0;
686 data
->size
= f
->dirent
.size
;
687 data
->atime
= f
->dirent
.atime
;
688 data
->ctime
= f
->dirent
.ctime
;
689 data
->mtime
= f
->dirent
.mtime
;
696 /*****************************************************************************/
699 smba_setattr (smba_file_t
* f
, smba_stat_t
* data
)
703 if (data
->atime
!= -1)
704 f
->dirent
.atime
= data
->atime
;
706 if (data
->ctime
!= -1)
707 f
->dirent
.ctime
= data
->ctime
;
709 if (data
->mtime
!= -1)
710 f
->dirent
.mtime
= data
->mtime
;
713 f
->dirent
.attr
|= aRONLY
;
715 f
->dirent
.attr
&= ~aRONLY
;
717 if (data
->is_archive
)
718 f
->dirent
.attr
|= aARCH
;
720 f
->dirent
.attr
&= ~aARCH
;
723 f
->dirent
.attr
|= aSYSTEM
;
725 f
->dirent
.attr
&= ~aSYSTEM
;
729 if ((errnum
= write_attr (f
)) < 0)
732 if (data
->size
!= -1 &&
733 data
->size
!= (int)f
->dirent
.size
)
735 if ((errnum
= make_open (f
, 1)) < 0)
738 if ((errnum
= smb_proc_trunc (&f
->server
->server
, f
->dirent
.fileid
, data
->size
)) < 0)
741 f
->dirent
.size
= data
->size
;
749 /*****************************************************************************/
752 smba_readdir (smba_file_t
* f
, long offs
, void *d
, smba_callback_t callback
)
754 int cache_index
, rval
, o
, eof
, count
= 0;
755 long now
= GetCurrentTime();
758 rval
= make_open (f
, 0);
762 if (f
->dircache
== NULL
) /* get a cache */
764 dircache_t
* dircache
= f
->server
->dircache
;
766 if (dircache
->cache_for
!= NULL
)
767 dircache
->cache_for
->dircache
= NULL
; /* steal it */
769 dircache
->eof
= dircache
->len
= dircache
->base
= 0;
770 dircache
->cache_for
= f
;
772 f
->dircache
= dircache
;
774 LOG (("stealing cache\n"));
778 if ((now
- f
->dircache
->created_at
) >= DIR_CACHE_TIME
)
780 f
->dircache
->eof
= f
->dircache
->len
= f
->dircache
->base
= 0;
782 LOG (("cache outdated\n"));
786 for (cache_index
= offs
; ; cache_index
++)
788 if (cache_index
< f
->dircache
->base
/* fill cache if necessary */
789 || cache_index
>= f
->dircache
->base
+ f
->dircache
->len
)
791 if (cache_index
>= f
->dircache
->base
+ f
->dircache
->len
&& f
->dircache
->eof
)
792 break; /* nothing more to read */
794 LOG (("cachefill for %s\n", f
->dirent
.complete_path
));
795 LOG (("\tbase was: %ld, len was: %ld, newbase=%ld\n", f
->dircache
->base
, f
->dircache
->len
, cache_index
));
797 f
->dircache
->len
= 0;
798 f
->dircache
->base
= cache_index
;
800 rval
= smb_proc_readdir (&f
->server
->server
, f
->dirent
.complete_path
, cache_index
, f
->dircache
->cache_size
, f
->dircache
->cache
);
804 /* Avoid some hits if restart/retry occured. Should fix the real root
805 of this problem really, but I am not bored enough atm. -Piru
806 ZZZ this needs further investigation. */
807 if (f
->dircache
== NULL
)
809 LOG (("lost dircache due to an error, bailing out!\n"));
814 f
->dircache
->len
= rval
;
815 f
->dircache
->eof
= (rval
< f
->dircache
->cache_size
);
816 f
->dircache
->created_at
= now
;
818 LOG (("cachefill with %ld entries\n", rval
));
821 o
= cache_index
- f
->dircache
->base
;
822 eof
= (o
>= (f
->dircache
->len
- 1) && f
->dircache
->eof
);
825 LOG (("delivering '%s', cache_index=%ld, eof=%ld\n", f
->dircache
->cache
[o
].complete_path
, cache_index
, eof
));
827 data
.is_dir
= (f
->dircache
->cache
[o
].attr
& aDIR
) != 0;
828 data
.is_wp
= (f
->dircache
->cache
[o
].attr
& aRONLY
) != 0;
829 data
.is_hidden
= (f
->dircache
->cache
[o
].attr
& aHIDDEN
) != 0;
830 data
.is_system
= (f
->dircache
->cache
[o
].attr
& aSYSTEM
) != 0;
831 data
.is_archive
= (f
->dircache
->cache
[o
].attr
& aARCH
) != 0;
832 data
.size
= f
->dircache
->cache
[o
].size
;
833 data
.atime
= f
->dircache
->cache
[o
].atime
;
834 data
.ctime
= f
->dircache
->cache
[o
].ctime
;
835 data
.mtime
= f
->dircache
->cache
[o
].mtime
;
837 if ((*callback
) (d
, cache_index
, cache_index
+ 1, f
->dircache
->cache
[o
].complete_path
, eof
, &data
))
849 /*****************************************************************************/
852 invalidate_dircache (struct smba_server
* server
, char * path
)
854 dircache_t
* dircache
= server
->dircache
;
855 char other_path
[SMB_MAXNAMELEN
+ 1];
863 strlcpy(other_path
,path
,sizeof(other_path
));
865 len
= strlen(other_path
);
866 for(i
= len
-1 ; i
>= 0 ; i
--)
870 other_path
[0] = DOS_PATHSEP
;
871 other_path
[1] = '\0';
873 else if (other_path
[i
] == DOS_PATHSEP
)
875 other_path
[i
] = '\0';
882 other_path
[0] = '\0';
885 SHOWSTRING(other_path
);
887 if(dircache
->cache_for
!= NULL
)
888 SHOWSTRING(dircache
->cache_for
->dirent
.complete_path
);
890 SHOWMSG("-- directory cache is empty --");
892 if(path
== NULL
|| (dircache
->cache_for
!= NULL
&& CompareNames(other_path
,dircache
->cache_for
->dirent
.complete_path
) == SAME
))
894 SHOWMSG("clearing directory cache");
896 dircache
->eof
= dircache
->len
= dircache
->base
= 0;
897 if(dircache
->cache_for
!= NULL
)
899 dircache
->cache_for
->dircache
= NULL
;
900 dircache
->cache_for
= NULL
;
907 /*****************************************************************************/
910 smba_create (smba_file_t
* dir
, const char *name
, smba_stat_t
* attr
)
912 struct smb_dirent entry
;
916 errnum
= make_open (dir
, 0);
920 memset (&entry
, 0, sizeof (entry
));
923 entry
.attr
|= aRONLY
;
925 if (attr
->is_archive
)
929 entry
.attr
|= aSYSTEM
;
931 entry
.atime
= entry
.mtime
= entry
.ctime
= GetCurrentTime();
933 path
= malloc (strlen (name
) + dir
->dirent
.len
+ 2);
940 memcpy (path
, dir
->dirent
.complete_path
, dir
->dirent
.len
);
941 path
[dir
->dirent
.len
] = DOS_PATHSEP
;
942 strcpy (&path
[dir
->dirent
.len
+ 1], name
);
944 errnum
= smb_proc_create (&dir
->server
->server
, path
, strlen (path
), &entry
);
946 invalidate_dircache (dir
->server
, path
);
955 /*****************************************************************************/
958 smba_mkdir (smba_file_t
* dir
, const char *name
)
963 errnum
= make_open (dir
, 0);
967 path
= malloc (strlen (name
) + dir
->dirent
.len
+ 2);
974 memcpy (path
, dir
->dirent
.complete_path
, dir
->dirent
.len
);
975 path
[dir
->dirent
.len
] = DOS_PATHSEP
;
976 strcpy (&path
[dir
->dirent
.len
+ 1], name
);
978 errnum
= smb_proc_mkdir (&dir
->server
->server
, path
, strlen (path
));
980 invalidate_dircache (dir
->server
, path
);
989 /*****************************************************************************/
992 close_path (smba_server_t
* s
, char *path
)
996 for (p
= (smba_file_t
*)s
->open_files
.mlh_Head
;
997 p
->node
.mln_Succ
!= NULL
;
998 p
= (smba_file_t
*)p
->node
.mln_Succ
)
1000 if (p
->is_valid
&& CompareNames(p
->dirent
.complete_path
, path
) == SAME
)
1002 if (p
->dirent
.opened
)
1003 smb_proc_close (&s
->server
, p
->dirent
.fileid
, p
->dirent
.mtime
);
1005 p
->dirent
.opened
= 0;
1011 /*****************************************************************************/
1014 smba_remove (smba_server_t
* s
, char *path
)
1018 close_path (s
, path
);
1020 result
= smb_proc_unlink (&s
->server
, path
, strlen (path
));
1022 invalidate_dircache (s
, path
);
1027 /*****************************************************************************/
1030 smba_rmdir (smba_server_t
* s
, char *path
)
1034 close_path (s
, path
);
1036 result
= smb_proc_rmdir (&s
->server
, path
, strlen (path
));
1038 invalidate_dircache (s
, path
);
1043 /*****************************************************************************/
1046 smba_rename (smba_server_t
* s
, char *from
, char *to
)
1050 close_path (s
, from
);
1052 result
= smb_proc_mv (&s
->server
, from
, strlen (from
), to
, strlen (to
));
1054 invalidate_dircache (s
, from
);
1059 /*****************************************************************************/
1062 smba_statfs (smba_server_t
* s
, long *bsize
, long *blocks
, long *bfree
)
1064 struct smb_dskattr dskattr
;
1067 errnum
= smb_proc_dskattr (&s
->server
, &dskattr
);
1071 (*bsize
) = dskattr
.blocksize
* dskattr
.allocblocks
;
1072 (*blocks
) = dskattr
.total
;
1073 (*bfree
) = dskattr
.free
;
1080 /*****************************************************************************/
1083 smb_invalidate_all_inodes (struct smb_server
*server
)
1087 invalidate_dircache (server
->abstraction
, NULL
);
1089 for (f
= (smba_file_t
*)server
->abstraction
->open_files
.mlh_Head
;
1090 f
->node
.mln_Succ
!= NULL
;
1091 f
= (smba_file_t
*)f
->node
.mln_Succ
)
1093 f
->dirent
.opened
= 0;
1098 /*****************************************************************************/
1101 smba_cleanup_dircache(struct smba_server
* server
)
1103 dircache_t
* the_dircache
= server
->dircache
;
1105 if(the_dircache
!= NULL
)
1109 for (i
= 0; i
< the_dircache
->cache_size
; i
++)
1111 if(the_dircache
->cache
[i
].complete_path
!= NULL
)
1112 free(the_dircache
->cache
[i
].complete_path
);
1116 server
->dircache
= NULL
;
1121 smba_setup_dircache (struct smba_server
* server
,int cache_size
)
1123 dircache_t
* the_dircache
;
1124 int error
= (-ENOMEM
);
1127 the_dircache
= malloc(sizeof(*the_dircache
) + (cache_size
-1) * sizeof(the_dircache
->cache
));
1128 if(the_dircache
== NULL
)
1131 memset(the_dircache
,0,sizeof(*the_dircache
));
1132 the_dircache
->cache_size
= cache_size
;
1134 for (i
= 0; i
< the_dircache
->cache_size
; i
++)
1136 the_dircache
->cache
[i
].complete_path
= malloc (SMB_MAXNAMELEN
+ 1);
1137 if(the_dircache
->cache
[i
].complete_path
== NULL
)
1140 the_dircache
->cache
[i
].complete_path_size
= SMB_MAXNAMELEN
+ 1;
1143 server
->dircache
= the_dircache
;
1151 if(the_dircache
!= NULL
)
1153 for (i
= 0; i
< the_dircache
->cache_size
; i
++)
1155 if(the_dircache
->cache
[i
].complete_path
!= NULL
)
1156 free(the_dircache
->cache
[i
].complete_path
);
1166 /*****************************************************************************/
1169 extract_service (char *service
, char *server
, size_t server_size
, char *share
, size_t share_size
)
1173 char *complete_service
;
1174 char * service_copy
;
1177 service_copy
= malloc(strlen(service
)+1);
1178 if(service_copy
== NULL
)
1181 ReportError("Not enough memory.");
1185 strcpy (service_copy
, service
);
1186 complete_service
= service_copy
;
1188 if (strlen (complete_service
) < 4 || complete_service
[0] != '/')
1191 ReportError("Invalid service name '%s'.",complete_service
);
1195 while (complete_service
[0] == '/')
1196 complete_service
+= 1;
1198 share_start
= strchr (complete_service
, '/');
1199 if (share_start
== NULL
)
1202 ReportError("Invalid share name '%s'.",complete_service
);
1206 (*share_start
++) = '\0';
1207 root_start
= strchr (share_start
, '/');
1209 if (root_start
!= NULL
)
1210 (*root_start
) = '\0';
1212 if ((strlen (complete_service
) > 63) || (strlen (share_start
) > 63))
1214 result
= -ENAMETOOLONG
;
1215 ReportError("Server or share name is too long in '%s' (max %ld characters).",service
,63);
1219 strlcpy (server
, complete_service
, server_size
);
1220 strlcpy (share
, share_start
, share_size
);
1224 if(service_copy
!= NULL
)
1231 smba_start(char * service
,char *opt_workgroup
,char *opt_username
,char *opt_password
,char *opt_clientname
,char *opt_servername
,int opt_cachesize
,smba_server_t
** result
)
1233 smba_connect_parameters_t par
;
1234 smba_server_t
*the_server
= NULL
;
1238 int use_extended
= 0;
1239 char server_name
[17], client_name
[17];
1240 char username
[64], password
[64];
1242 char server
[64], share
[64];
1243 unsigned int ipAddr
;
1247 (*username
) = (*password
) = (*server_name
) = (*client_name
) = '\0';
1249 error
= extract_service (service
, server
, sizeof(server
), share
, sizeof(share
));
1253 ipAddr
= inet_addr (server
);
1254 if (ipAddr
== INADDR_NONE
) /* name was given, not numeric */
1258 h
= gethostbyname (server
);
1259 lookup_error
= h_errno
;
1263 ipAddr
= ((struct in_addr
*)(h
->h_addr
))->s_addr
;
1265 else if (BroadcastNameQuery(server
,"",(UBYTE
*)&ipAddr
) != 0)
1267 ReportError("Unknown host '%s' (%ld, %s).",server
,lookup_error
,host_strerror(lookup_error
));
1274 char hostName
[MAXHOSTNAMELEN
+1];
1276 h
= gethostbyaddr ((char *) &ipAddr
, sizeof (ipAddr
), AF_INET
);
1279 ReportError("Unknown host '%s' (%ld, %s).",server
,h_errno
,host_strerror(errno
));
1284 /* Brian Willette: Now we will set the server name to the dns
1285 hostname, hopefully this will be the same as the netbios name for
1287 We do this because the user supplied no hostname, and we
1288 need one for netbios, this is the best guess choice we have
1289 NOTE: If the names are different between DNS and netbios on
1290 the windows side, the user MUST use the -s option. */
1291 for (i
= 0; h
->h_name
[i
] != '.' && h
->h_name
[i
] != '\0' && i
< 255; i
++)
1292 hostName
[i
] = h
->h_name
[i
];
1296 /* Make sure the hostname is 16 characters or less (for Netbios) */
1297 if (strlen (hostName
) > 16)
1299 ReportError("Server host name '%s' is too long (max %ld characters).", hostName
, 16);
1300 error
= (-ENAMETOOLONG
);
1304 strlcpy (server_name
, hostName
, sizeof(server_name
));
1307 if(opt_password
!= NULL
)
1309 if(strlen(opt_password
) >= sizeof(password
))
1311 ReportError("Password is too long (max %ld characters).", sizeof(password
)-1);
1312 error
= (-ENAMETOOLONG
);
1316 strlcpy(password
,opt_password
,sizeof(password
));
1319 if(strlen(opt_username
) >= sizeof(username
))
1321 ReportError("User name '%s' is too long (max %ld characters).", username
,sizeof(username
)-1);
1322 error
= (-ENAMETOOLONG
);
1326 strlcpy(username
,opt_username
,sizeof(username
));
1327 StringToUpper(username
);
1329 if (strlen(opt_workgroup
) > 15)
1331 ReportError("Workgroup/domain name '%s' is too long (max %ld characters).", opt_workgroup
,15);
1332 error
= (-ENAMETOOLONG
);
1336 strlcpy (workgroup
, opt_workgroup
, sizeof(workgroup
));
1337 StringToUpper (workgroup
);
1339 if(opt_servername
!= NULL
)
1341 if (strlen (opt_servername
) > 16)
1343 ReportError("Server name '%s' is too long (max %ld characters).", opt_servername
,16);
1344 error
= (-ENAMETOOLONG
);
1348 strlcpy (server_name
, opt_servername
, sizeof(server_name
));
1351 if(opt_clientname
!= NULL
)
1353 if (strlen (opt_clientname
) > 16)
1355 ReportError("Client name '%s' is too long (max %ld characters).", opt_clientname
,16);
1356 error
= (-ENAMETOOLONG
);
1360 strlcpy (client_name
, opt_clientname
, sizeof(client_name
));
1363 if(opt_cachesize
< 1)
1364 opt_cachesize
= DIRCACHE_SIZE
;
1365 else if (opt_cachesize
< 10)
1368 strlcpy(par
.server_ipname
,server
,sizeof(par
.server_ipname
));
1369 par
.server_name
= server_name
;
1370 par
.client_name
= client_name
;
1372 strlcpy(par
.service
,share
,sizeof(par
.service
));
1373 par
.username
= username
;
1374 par
.password
= password
;
1375 par
.max_xmit
= max_xmit
;
1377 error
= smba_connect (&par
, ipAddr
, use_extended
, workgroup
, opt_cachesize
, &the_server
);
1380 ReportError("Could not connect to server (%ld, %s).",-error
,amitcp_strerror(-error
));
1384 (*result
) = the_server
;
1393 /*****************************************************************************/
1396 smba_get_dircache_size(struct smba_server
* server
)
1400 result
= server
->dircache
->cache_size
;
1405 /*****************************************************************************/
1408 smba_change_dircache_size(struct smba_server
* server
,int cache_size
)
1410 dircache_t
* new_cache
;
1411 dircache_t
* the_dircache
= server
->dircache
;
1415 result
= the_dircache
->cache_size
;
1420 if(cache_size
== the_dircache
->cache_size
)
1423 new_cache
= malloc(sizeof(*new_cache
) + (cache_size
-1) * sizeof(new_cache
->cache
));
1424 if(new_cache
== NULL
)
1427 memset(new_cache
,0,sizeof(*new_cache
));
1428 new_cache
->cache_size
= cache_size
;
1430 /* If the new cache is to be larger than the old one,
1431 allocate additional file name slots. */
1432 if(cache_size
> the_dircache
->cache_size
)
1434 for(i
= the_dircache
->cache_size
; i
< cache_size
; i
++)
1436 new_cache
->cache
[i
].complete_path
= malloc (SMB_MAXNAMELEN
+ 1);
1437 if(new_cache
->cache
[i
].complete_path
== NULL
)
1441 for(j
= the_dircache
->cache_size
; j
< i
; j
++)
1442 free(new_cache
->cache
[j
].complete_path
);
1449 new_cache
->cache
[i
].complete_path_size
= SMB_MAXNAMELEN
+ 1;
1452 /* Reuse the file name buffers allocated for
1454 for(i
= 0 ; i
< the_dircache
->cache_size
; i
++)
1456 new_cache
->cache
[i
].complete_path
= the_dircache
->cache
[i
].complete_path
;
1457 new_cache
->cache
[i
].complete_path_size
= the_dircache
->cache
[i
].complete_path_size
;
1459 the_dircache
->cache
[i
].complete_path
= NULL
;
1464 /* Reuse the file name buffers allocated for
1466 for(i
= 0 ; i
< cache_size
; i
++)
1468 new_cache
->cache
[i
].complete_path
= the_dircache
->cache
[i
].complete_path
;
1469 new_cache
->cache
[i
].complete_path_size
= the_dircache
->cache
[i
].complete_path_size
;
1470 the_dircache
->cache
[i
].complete_path
= NULL
;
1474 invalidate_dircache(server
, NULL
);
1476 for (i
= 0; i
< the_dircache
->cache_size
; i
++)
1478 if(the_dircache
->cache
[i
].complete_path
!= NULL
)
1479 free(the_dircache
->cache
[i
].complete_path
);
1484 server
->dircache
= new_cache
;
1485 result
= cache_size
;