From 3a06bbdacff65ce35279cf67906e6597489be69b Mon Sep 17 00:00:00 2001 From: obarthel Date: Sat, 15 Sep 2018 11:56:09 +0200 Subject: [PATCH] Updated to version 1.181 Please keep in mind that this is still a development version and might surprise you (not necessarily in a good way). Do not let me discourage you to build and test this version, although there will be some risks involved such as data corruption or loss of data. --- README.md | 10 + documentation/history.doc | 37 + documentation/smbfs.doc | 308 ++++---- source_code/dump_smb.c | 14 +- source_code/main.c | 1278 ++++++++++++++++++++------------- source_code/proc.c | 26 +- source_code/smb_abstraction.c | 62 +- source_code/smb_abstraction.h | 2 +- source_code/smbfs.h | 4 +- source_code/smbfs_rev.h | 10 +- source_code/smbfs_rev.rev | 2 +- source_code/sock.c | 6 +- 12 files changed, 1070 insertions(+), 689 deletions(-) diff --git a/README.md b/README.md index b34970e..63afc8a 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,16 @@ Note that the **smbfs** program may not quit immediately. It may have to wait un You may have to send more than one `Break` command to stop the **smbfs** program. +### 4.3. Temporarily disabling the file system + +If, for example, you need to temporarily shut down the network, **smbfs** will be unable to do its job, at least until the network becomes operational again. In the mean time *Workbench* and other programs will keep accessing the file system and may get stuck. + +You can avoid most of these problems by temporarily disabling the file system until it can access the network again. For this to work, you need to start the **smbfs** program in the shell and use the `VOLUMENAME` option, which will make a disk icon appear in the *Workbench* window. + +To disable the file system, hit the `[Ctrl]+D` keys or use the `Break` command (e.g. `Break 10 D` if **smbfs** is running as process number 10). + +To re-enable the file system again, hit the `[Ctrl]+E` keys or use the `Break` command (e.g. `Break 10 E` if **smbfs** is running as process number 10). + ## 5. Startup options diff --git a/documentation/history.doc b/documentation/history.doc index 9cc9ecb..b99782f 100644 --- a/documentation/history.doc +++ b/documentation/history.doc @@ -2536,3 +2536,40 @@ smbfs 1.177 (27.8.2018) - Added more debug output in order to find that pesky AsyncWB batch rename problem :-/ + + +smbfs 1.178 (29.8.2018) + +- Unified and simplified even more commonly-used code. + +- Debug output now includes how many packets are currently waiting + to be processed and how much time it took to process each + single packet. + +- Modified the string formatting code to respect buffer size limitations. + + +smbfs 1.179 (2.9.2018) + +- Cleaned up the debug code, removing unnecessary line feed characters + and fixing the broken protection flag output. + + +smbfs 1.180 (15.9.2018) + +- The ACTION_INHIBIT packet is now rejected as "not known" since this + file system cannot actually support it properly. + +- If you provided the file system with a volume name, then you can + disable/enable the file system (as if the medium had been removed from + a CD-ROM or floppy disk drive) with the [Ctrl]+D (= disable) + and [Ctrl]+E (= enable) keys. + + +smbfs 1.181 (15.9.2018) + +- ACTION_FREE_LOCK now correctly returns an error if the file lock in + question cannot be freed. For example, this may happen if the + file system is currently disabled. + +- Updated the documentation. diff --git a/documentation/smbfs.doc b/documentation/smbfs.doc index 0665f16..15f4681 100644 --- a/documentation/smbfs.doc +++ b/documentation/smbfs.doc @@ -10,12 +10,12 @@ This file system can be used to access files made available by file servers which implement the SMBv1 protocol, such as Microsoft Windows or any other platform which supports the free Samba product. -These files can be accessed using shell commands such as "List", the -Workbench or utilities such as Directory Opus as if the file server were a -local disk drive. +These files can be accessed using shell commands such as "List", the Workbench +or utilities such as Directory Opus as if the file server were a local disk +drive. -You may find smbfs useful if you want to access a NAS -(network-attached storage) drive, or even a Linux file server. +You may find smbfs useful if you want to access a NAS (network-attached +storage) drive, or even a Linux file server. 2. What do you need to get started? @@ -85,12 +85,11 @@ would be "ARBEITSGRUPPE". 4. Starting and stopping the file system -smbfs is an uncommon kind of file system in that you do not use the -"Mount" command to mount it. In fact, smbfs is a program which can be -launched from the shell, using command line parameters to tell it which -resources should be used. But you can also start it from Workbench: in this -case you would have to put the program's command line options into icon tool -types. +smbfs is an uncommon kind of file system in that you do not use the "Mount" +command to mount it. In fact, smbfs is a program which can be launched from +the shell, using command line parameters to tell it which resources should be +used. But you can also start it from Workbench: in this case you would have to +put the program's command line options into icon tool types. 4.1. Starting the file system @@ -126,10 +125,9 @@ error messages it may produce. 4.2. Stopping the file system -How do you "unmount" the file system? Stopping the smbfs program will -unmount the file system. This can be accomplished by either hitting the -[Ctrl]+C keys or by using the "Status" shell command and then the "Break" -command. +How do you "unmount" the file system? Stopping the smbfs program will unmount +the file system. This can be accomplished by either hitting the [Ctrl]+C keys +or by using the "Status" shell command and then the "Break" command. For example, the "Status" shell command may produce the following output: @@ -145,8 +143,7 @@ For example, the "Status" shell command may produce the following output: Process 10: Loaded as command: SMBFS '//sourcery/all' Look at the last line describing process number 10: it shows the name of the -file system program smbfs and the name of the SMB share it is connected -to. +file system program smbfs and the name of the SMB share it is connected to. To stop this file system and effectively unmount it, use the shell "Break" command; in this case you would enter "Break 10" to stop the file system. @@ -155,8 +152,25 @@ Note that the smbfs program may not quit immediately. It may have to wait until the last client has released all the resources it obtained from the file system. -You may have to send more than one "Break" command to stop the smbfs -program. +You may have to send more than one "Break" command to stop the smbfs program. + +4.3. Temporarily disabling the file system + +If, for example, you need to temporarily shut down the network, smbfs will be +unable to do its job, at least until the network becomes operational again. In +the mean time Workbench and other programs will keep accessing the file system +and may get stuck. + +You can avoid most of these problems by temporarily disabling the file system +until it can access the network again. For this to work, you need to start the +smbfs program in the shell and use the VOLUMENAME option, which will make a +disk icon appear in the Workbench window. + +To disable the file system, hit the [Ctrl]+D keys or use the "Break" command +(e.g. "Break 10 D" if smbfs is running as process number 10). + +To re-enable the file system again, hit the [Ctrl]+E keys or use the "Break" +command (e.g. "Break 10 E" if smbfs is running as process number 10). 5. Startup options @@ -164,8 +178,7 @@ program. The smbfs program supports a number of options which control how it works. You can enter these options as command line parameters, or, if you start the -smbfs program from Workbench, you can set these options as icon tool -types. +smbfs program from Workbench, you can set these options as icon tool types. Here is how the options look like, in alphabetical order (as command line parameters): @@ -230,16 +243,16 @@ connection. The port number is optional, though. In place of the port (e.g. 445) number you can also use the name of a TCP/UDP service (e.g. "microsoft-ds"). -Finally, you need to tell the SMB server which service you want to connect -to, which for the smbfs program should be the name of a shared network -file system. In the example the name of the shared network file system would -be "share-name". +Finally, you need to tell the SMB server which service you want to connect to, +which for the smbfs program should be the name of a shared network file +system. In the example the name of the shared network file system would be +"share-name". 5.1.2. "USER=USERNAME/K" In order to connect to an SMB share, the server requires that a user name is -provided. If you omit the user name, the smbfs program will use "GUEST" as -a replacement. +provided. If you omit the user name, the smbfs program will use "GUEST" as a +replacement. If you do provide a user name, it must not be longer than 64 characters. The name you provide will be translated to all upper case characters. @@ -252,13 +265,13 @@ variable could be set up like this: Copy ENV:smbfs_username ENVARC: You may also use the "smbfs_user" environment variable in place of the -"smbfs_username" variable. The two are aliases for one another, but smbfs -will read only one of the two. +"smbfs_username" variable. The two are aliases for one another, but smbfs will +read only one of the two. 5.1.3. "PASSWORD/K" -You may not need to provide a password in order to connect to an SMB share. -If you omit it, the smbfs program will use an empty password. +You may not need to provide a password in order to connect to an SMB share. If +you omit it, the smbfs program will use an empty password. If you do need a password to go along with the user name, your password cannot be longer than 64 characters. @@ -271,24 +284,15 @@ variable could be set up like this: Copy ENV:smbfs_password ENVARC: Keep in mind that passwords like these really should not be exposed by storing -them in environment variables. But then the protocol smbfs uses is almost -as insecure as it gets anyway. +them in environment variables. But then the protocol smbfs uses is almost as +insecure as it gets anyway. The authentication process only works if the machine you are connecting to knows about the user name and password you want to use. As of this writing, -smbfs can only be used for authenticating against a password server that -is the same machine as the one on which you wish to access a share. +smbfs can only be used for authenticating against a password server that is +the same machine as the one on which you wish to access a share. -5.1.4. "NETBIOS/S" - -Older server software such as "Microsoft Windows XP" may not respond to the -requests of the smbfs program to connect to the shared network file system. - -If the connection attempt fails immediately you may want to try the "NETBIOS" -switch which tells the smbfs program to use an older protocol when trying to -talk to the server. - -5.1.5. "CHANGECASE/S" +5.1.4. "CHANGECASE/S" By default the password you provide with the "PASSWORD" option will not be changed before it is used for accessing the server's shared network file @@ -299,7 +303,7 @@ before it can be used. If this is necessary, you should either provide the password in this form or resort to the "CHANGECASE" option, which will cause it to be translated to all upper case characters. -5.1.6. "DOMAIN=WORKGROUP/K" +5.1.5. "DOMAIN=WORKGROUP/K" This option may be omitted, in which case the smbfs program will ask the file server about the work group which it is a member of. Should the server fail to @@ -322,16 +326,25 @@ You may also use the "smbfs_domain" environment variable in place of the "smbfs_workgroup" variable. The two are aliases for one another, but smbfs will read only one of the two. +5.1.6. "NETBIOS/S" + +Older server software such as "Microsoft Windows XP" may not respond to the +requests of the smbfs program to connect to the shared network file system. + +If the connection attempt fails immediately you may want to try the "NETBIOS" +switch which tells the smbfs program to use an older protocol when trying to +talk to the server. + 5.1.7. "CLIENT=CLIENTNAME/K" -The smbfs program will attempt to connect to the file server by providing -the name of the computer you connect from. +The smbfs program will attempt to connect to the file server by providing the +name of the computer you connect from. In some cases this may be undesirable as the computer's name differs from what the file server expects. -You can use the "CLIENT" parameter to tell smbfs under which name it -should announce itself to the server. +You can use the "CLIENT" parameter to tell smbfs under which name it should +announce itself to the server. This parameter is optional and will be translated to all upper case characters; it cannot be longer than 16 characters. @@ -375,18 +388,18 @@ containing reserved characters, will be "hidden" as well. 5.2.1. "UNICODE/K" The built-in default translation method is restricted to the part of Unicode -which is covered by the ISO-8859-1 character set. It is enabled by default, -as if "UNICODE=on" had been used. You can disable it with "UNICODE=off", which +which is covered by the ISO-8859-1 character set. It is enabled by default, as +if "UNICODE=on" had been used. You can disable it with "UNICODE=off", which completely disables the translation. Note: some Samba versions will return corrupted file and drawer names unless -Unicode support is enabled. Names which use only US-ASCII characters will not -be corrupted. +Unicode support is enabled. Names which use only US-ASCII characters appear to +be generally safe to use and are unlikely to suffer from corruption. 5.2.2. "CP437/S" The switch "CP437" enables a code page-based translation which works well -enough with old Samba servers. "CP437" stands for "code page 437", which is +enough with old Samba versions. "CP437" stands for "code page 437", which is what the original IBM-PC would use. The "CP437" switch disables Unicode support. @@ -394,7 +407,7 @@ The "CP437" switch disables Unicode support. 5.2.3. "CP850/S" The switch "CP850" enables a code page-based translation which works well -enough with old Samba servers. "CP850" stands for "code page 850", which is a +enough with old Samba versions. "CP850" stands for "code page 850", which is a variant of what the original IBM-PC would use. This variant is intended to be used in western Europe and is more compatible with the ISO-8859-1 character set than the "CP437" variant. @@ -416,15 +429,17 @@ In most cases the "L:FileSystem_Trans/INTL.crossdos" translation table file should be sufficient. To specify which file contains the translation tables to use you would use the -"TRANSLATIONFILE" parameter, e.g. TRANSLATIONFILE=L:FileSystem_Trans/INTL.crossdos +"TRANSLATIONFILE" parameter, e.g. "TRANSLATIONFILE=L:FileSystem_Trans/INTL.crossdos". +However, you might want to try the "CP850" switch instead which should produce +the same effect. The "TRANSLATE" option disables Unicode support. 5.3. Performance tuning -You may be able to put the smbfs program to good use, but overall -performance, reliability and memory usage may still be somewhat lacking. These -aspects may be tuned with the following parameters. +You may be able to put the smbfs program to good use, but overall performance, +reliability and memory usage may still be somewhat lacking. These aspects may +be tuned with the following parameters. 5.3.1. "CACHE=CACHESIZE/N/K" @@ -441,8 +456,8 @@ using the "CACHESIZE" parameter. The size of the cache cannot be smaller than 5.3.2. "RAISEPRIORITY/S" -The smbfs program can be run at a higher priority than it would normally -do (normal would be priority 0), which might increase performance, but raise +The smbfs program can be run at a higher priority than it would normally do +(normal would be priority 0), which might increase performance, but raise system load, too. If the "RAISEPRIORITY" switch is used, the smbfs program will run at the same priority as other Amiga file systems do (this would be priority 10). @@ -454,16 +469,16 @@ operations. While it will try to reestablish a connection to the server, some time has to pass before it becomes clear that the server connection is no longer working correctly. -You can set the number of seconds which have to pass before the smbfs -program will stop waiting for the server to respond, shut down the connection -and try again. For example, "TIMEOUT=5" will select a timeout of 5 seconds. +You can set the number of seconds which have to pass before the smbfs program +will stop waiting for the server to respond, shut down the connection and try +again. For example, "TIMEOUT=5" will select a timeout of 5 seconds. 5.3.4. "WRITEBEHIND/S" -The smbfs program can try to improve write performance by not waiting for -the server to confirm that all the data just transmitted has in fact been -stored. There is a risk involved in that the server may not have been able to -store the data and you will never know about it. +The smbfs program can try to improve write performance by not waiting for the +server to confirm that all the data just transmitted has in fact been stored. +There is a risk involved in that the server may not have been able to store +the data and you will never know about it. Please note that the "WRITEBEHIND" switch has no effect if "PROTOCOL=nt1" is used because the smbfs program will then be using a different server write @@ -491,8 +506,8 @@ different. There is a catch though: the AmigaDOS file naming scheme does not follow this model and you may run into problems when you are trying to use it. -By default, the smbfs program does not treat file and drawer names -differently which only differ with respect to the case of letters. +By default, the smbfs program does not treat file and drawer names differently +which only differ with respect to the case of letters. 5.4.2. "DISABLEEXALL/S" @@ -504,21 +519,21 @@ a time, and no name may be longer than 107 characters. The second method ("ExAll"), introduced with Kickstart 2.0, can deliver more entries and more quickly than the original method. Also, directory entry names -may be longer than "just" 107 characters (the smbfs program supports file -and drawer names of up to 255 characters). +may be longer than "just" 107 characters (the smbfs program supports file and +drawer names of up to 255 characters). The smbfs program supports both methods, but there is a catch: Some Amiga software struggles to handle the number of entries delivered by the "ExAll" method, and names longer than 30 characters are a problem. Such software may malfunction and even crash. -To avoid problems with such software, the smbfs program can be made to -pretend that it did not support the "ExAll" method. Use the "DISABLEEXALL" -switch to disable the "ExAll" method. +To avoid problems with such software, the smbfs program can be made to pretend +that it did not support the "ExAll" method. Use the "DISABLEEXALL" switch to +disable the "ExAll" method. -Please note that if the "DISABLEEXALL" switch is used, the smbfs program -will make files and drawers appear to be "hidden" if their names are longer -than 107 characters. +Please note that if the "DISABLEEXALL" switch is used, the smbfs program will +make files and drawers appear to be "hidden" if their names are longer than +107 characters. 5.4.3. "MAXNAMELEN/N/K" @@ -526,17 +541,16 @@ Some Amiga programs struggle with file and drawer names longer than 30 characters. They may malfunction and even crash when the smbfs program delivers them. -You can tell the smbfs program not to deliver any file or drawer names -which are longer than a certain number of characters using the "MAXNAMELEN" -option. For example, "MAXNAMELEN=30" would make files and drawers appear to be +You can tell the smbfs program not to deliver any file or drawer names which +are longer than a certain number of characters using the "MAXNAMELEN" option. +For example, "MAXNAMELEN=30" would make files and drawers appear to be "hidden" if their names are longer than 30 characters. 5.4.4. "MAXTRANSMIT/N/K" -You can fine-tune the size of the transmission buffer which the smbfs -program uses when reading and writing files. The server may not have picked a -buffer size which suits smbfs well. You can choose a smaller buffer size, -if needed. +You can fine-tune the size of the transmission buffer which the smbfs program +uses when reading and writing files. The server may not have picked a buffer +size which suits smbfs well. You can choose a smaller buffer size, if needed. The minimum transmission buffer size is 8000 bytes (this is also the default buffer size), and the maximum permitted size is 65535 bytes. @@ -546,23 +560,22 @@ accepted by the file server, which may choose to use a much smaller buffer. 5.4.5. "PROTOCOL/K" -The smbfs program talks to the file server using a protocol called -SMBv1, using commands and data structures described by the Common -Internet File System documentation. +The smbfs program talks to the file server using a protocol called SMBv1, +using commands and data structures described by the Common Internet File +System documentation. -There are several versions of the SMBv1 protocol in use, and depending -upon how old the server software is, smbfs may not work well with the file -server. +There are several versions of the SMBv1 protocol in use, and depending upon +how old the server software is, smbfs may not work well with the file server. -It may help if you change the protocol level which the smbfs program uses. -The default is "PROTOCOL=core" which should work well enough with SMB server -software available before 2009, and which is particularly suited for use -with the Samba server software. How do you know if the Samba* server software -is being used? Unless you are connecting to a Microsoft Windows server, you -can practically assume that Samba will provide the shared network file system. +It may help if you change the protocol level which the smbfs program uses. The +default is "PROTOCOL=core" which should work well enough with SMB server +software available before 2009, and which is particularly suited for use with +the Samba server software. How do you know if the Samba* server software is +being used? Unless you are connecting to a Microsoft Windows server, you can +practically assume that Samba will provide the shared network file system. -The alternative is "PROTOCOL=nt1" which might provide better compatibility -and performance with Microsoft Windows systems. +The alternative is "PROTOCOL=nt1" which might provide better compatibility and +performance with Microsoft Windows systems. When in doubt, stick with "PROTOCOL=core". @@ -576,33 +589,23 @@ With UNICODE=ON the SESSIONSETUP=DELAY option will delay enabling Unicode support until after the session has been established. SESSIONSETUP=NODELAY will enable Unicode support at the earliest possible time instead. -The default is SESSIONSETUP=DELAY which works both with Samba, and seems -to be required for Microsoft Windows systems. +The default is SESSIONSETUP=DELAY which works both with Samba, and seems to be +required for Microsoft Windows systems. 5.5. Time conversion -The file server which the smbfs program connects to may not share the -exact system time with your Amiga. Typically, it will expect file and drawer +The file server which the smbfs program connects to may not share the exact +system time with your Amiga. Typically, it will expect file and drawer modification time information to be recorded in Universally Coordinated Time (UTC), rather than your local time zone (and the effects of daylight savings time). You can, and should tell the smbfs program how far the local Amiga time -deviates from UTC. By default the smbfs program will try to use the time -zone information configured in the "Locale" preferences. This may not be +deviates from UTC. By default the smbfs program will try to use the time zone +information configured in the "Locale" preferences. This may not be sufficient, or even the wrong choice. -5.5.1. "DST=DSTOFFSET/N/K" - -This option can be used to adjust the file date stamps to take local daylight -savings time into account. - -The number to specify here is by how many minutes local time has been moved -ahead, which is typically 60. Note that smbfs does not know when daylight -savings time begins and ends. It is up to you to select the correct adjustment -value when appropriate. - -5.5.2. "TZ=TIMEZONEOFFSET/N/K" +5.5.1. "TZ=TIMEZONEOFFSET/N/K" By default the file system will use the current Locale settings to translate between the local time and the time used by the file server. @@ -616,12 +619,26 @@ order to translate it into the corresponding UTC value. For example, in central Europe using CET, you would use "TZ=60" since CET is one hour ahead of UTC. +If you use the "TIMEZONEOFFSET" option, then the smbfs program will ignore the +time zone information configured in the "Locale" preferences. + +5.5.2. "DST=DSTOFFSET/N/K" + +This option can be used to adjust the file date stamps to take local daylight +savings time into account. + +The number to specify here is by how many minutes local time has been moved +ahead, which is typically 60. + +Note that smbfs does not know when daylight savings time begins and ends. It +is up to you to select the correct adjustment value when appropriate. + 5.6. Miscellaneous 5.6.1. "DEVICE=DEVICENAME/K" and "VOLUME=VOLUMENAME/K" -The smbfs program can announce itself as an AmigaDOS file system by using -one of two different methods. +The smbfs program can announce itself as an AmigaDOS file system by using one +of two different methods. The first method involves announcing itself only as a file system device. This should be sufficient in most cases but has a drawback in that the device will @@ -630,8 +647,8 @@ icon. You tell smbfs to use a specific device name by using the "DEVICE" command line parameter, e.g. "DEVICE=SMBFS:". Note that device names must be unique, -i.e. there must be no other device by the same name in the system; smbfs -will report an error and exit if it finds one. +i.e. there must be no other device by the same name in the system; smbfs will +report an error and exit if it finds one. The second method involves announcing itself as a volume. This has the benefit of making the file system usable from Workbench since a disk icon will appear @@ -641,23 +658,23 @@ You tell smbfs to use a specific volume name by using the "VOLUME" command line parameter, e.g. "VOLUME=Sourcery:". Both methods have advantages and drawbacks. The drawback of the "VOLUME" -method is that it may deadlock the native Amiga Samba port as soon as the -file system is mounted. The drawback of the "DEVICE" method is that the file -system will not be usable from Workbench. +method is that it may deadlock the native Amiga Samba port as soon as the file +system is mounted. The drawback of the "DEVICE" method is that the file system +will not be usable from Workbench. If you wish, you can combine both methods; this is the approach most other file systems use. And in fact, when you tell smbfs to add a volume it will also add a device to go along with it. -The "VOLUME" and "DEVICE" keywords are optional; if you omit both, smbfs -will pretend that you had used the "DEVICE=SMBFS:" parameter. +The "VOLUME" and "DEVICE" keywords are optional; if you omit both, smbfs will +pretend that you had used the "DEVICE=SMBFS:" parameter. 5.6.2. "OMITHIDDEN/S" When requesting a directory listing, the file server may return some files and -drawers tagged as being hidden. By default smbfs will not treat these -"hidden" entries any different from the other directory entries, i.e. they are -not hidden from view. +drawers tagged as being hidden. By default smbfs will not treat these "hidden" +entries any different from the other directory entries, i.e. they are not +hidden from view. You can request that the hidden entries should be omitted from directory listings by using the "OMITHIDDEN" switch. @@ -667,8 +684,8 @@ to open and examine it. 5.6.3. "QUIET/S" -When started from shell, the smbfs program will print a message as soon as -the connection to the file server has been established. +When started from shell, the smbfs program will print a message as soon as the +connection to the file server has been established. If you do not want to see that message displayed, use the "QUIET" parameter. Please note that the smbfs program may still show error messages. @@ -699,7 +716,7 @@ level greater than 0, e.g. "DEBUG=2". The larger the number you specify the more debugging output will be created. Note that unless you state which file the debug output should be written to, -all debugging output will be sent to the shell. +all debugging output will be sent to the shell window. If you launched the smbfs program from Workbench, debug output will be produced using the operating system's debug output functionality which @@ -709,10 +726,10 @@ background. 6. Known problems -The design of smbfs follows the original file system concept behind the -code which the "Sharity-Light" file system is based upon. And that is a -Unix file system which differs from Amiga specific file systems in many -ways which can lead to problems which are discussed briefly below: +The design of smbfs follows the original file system concept behind the code +which the "Sharity-Light" file system is based upon. And that is a Unix file +system which differs from Amiga specific file systems in many ways which can +lead to problems which are discussed briefly below: - Single threaded design @@ -742,15 +759,14 @@ ways which can lead to problems which are discussed briefly below: even though it is empty or that for the same directory the same file may be reported twice in the listing. -While there are no easy solutions for any of these problems, it does not -mean that smbfs is unusable. You just have to be more careful when you -use the file system. For example, if a directory's contents cannot be -deleted due to one of the problems mentioned above, you might want to -retry later. +While there are no easy solutions for any of these problems, it does not mean +that smbfs is unusable. You just have to be more careful when you use the file +system. For example, if a directory's contents cannot be deleted due to one of +the problems mentioned above, you might want to retry later. -It should be noted that the problems described above are not inherent -to the original file system design. It's just that transferring that -design to an Amiga file system created the problems. +It should be noted that the problems described above are not inherent to the +original file system design. It's just that transferring that design to an +Amiga file system created the problems. 7. Credits @@ -797,5 +813,5 @@ smbfs is distributed under the terms of the GNU General Public License (version 2). The source code should have accompanied this program; if it hasn't, please contact the author for a copy. -The program was compiled using the SAS/C 6.58 compiler, with the Roadshow -SDK providing for the TCP/IP stack API header files. +The program was compiled using the SAS/C 6.58 compiler, with the Roadshow SDK +providing for the TCP/IP stack API header files. diff --git a/source_code/dump_smb.c b/source_code/dump_smb.c index 0106b1a..9ae30de 100644 --- a/source_code/dump_smb.c +++ b/source_code/dump_smb.c @@ -460,7 +460,7 @@ print_smb_data(struct line_buffer * lb,int num_data_bytes_left,const unsigned ch /* Print the row offset (in bytes) at the start of the * output line. */ - SPrintf(format_buffer,"%04lx:",row_offset); + LocalSNPrintf(format_buffer,sizeof(format_buffer),"%04lx:",row_offset); copy_string_to_line_buffer(lb,format_buffer,5,0); @@ -489,7 +489,7 @@ print_smb_data(struct line_buffer * lb,int num_data_bytes_left,const unsigned ch /* Convert this data byte to hexadecimal * representation. */ - SPrintf(format_buffer,"%02lx",c); + LocalSNPrintf(format_buffer,sizeof(format_buffer),"%02lx",c); strcat(dword_buffer,format_buffer); dword_buffer_len += 2; @@ -586,7 +586,7 @@ convert_filetime_to_string(const unsigned long * qword) tm = convert_filetime_to_tm(qword); - SPrintf(string,"%ld-%02ld-%02ldT%02ld:%02ld:%02ldZ", + LocalSNPrintf(string,sizeof(string),"%ld-%02ld-%02ldT%02ld:%02ld:%02ldZ", tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday, tm->tm_hour,tm->tm_min,tm->tm_sec); @@ -603,7 +603,7 @@ convert_smb_date_time_to_string(unsigned short smb_date,unsigned short smb_time) tm = convert_smb_date_time_to_tm(smb_date,smb_time); - SPrintf(string,"%ld-%02ld-%02ldT%02ld:%02ld:%02ldZ", + LocalSNPrintf(string,sizeof(string),"%ld-%02ld-%02ldT%02ld:%02ld:%02ldZ", tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday, tm->tm_hour,tm->tm_min,tm->tm_sec); @@ -621,7 +621,7 @@ convert_utime_to_string(unsigned long utime) tm = gmtime(&when); - SPrintf(string,"%ld-%02ld-%02ldT%02ld:%02ld:%02ldZ", + LocalSNPrintf(string,sizeof(string),"%ld-%02ld-%02ldT%02ld:%02ld:%02ldZ", tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday, tm->tm_hour,tm->tm_min,tm->tm_sec); @@ -978,7 +978,7 @@ print_smb_transaction2_subcommand(int command,enum smb_packet_source_t smb_packe { char code_string[40]; - SPrintf(code_string,"<%02lx%02ld>",unicode_char >> 8,unicode_char & 0xff); + LocalSNPrintf(code_string,sizeof(code_string),"<%02lx%02ld>",unicode_char >> 8,unicode_char & 0xff); copy_string_to_line_buffer(&lb,code_string,strlen(code_string),output_offset); output_offset += strlen(code_string); @@ -2361,7 +2361,7 @@ print_smb_contents(const struct smb_header * header,int command,enum smb_packet_ { char code_string[40]; - SPrintf(code_string,"<%02lx%02ld>",unicode_char >> 8,unicode_char & 0xff); + LocalSNPrintf(code_string,sizeof(code_string),"<%02lx%02ld>",unicode_char >> 8,unicode_char & 0xff); copy_string_to_line_buffer(&lb,code_string,strlen(code_string),output_offset); output_offset += strlen(code_string); diff --git a/source_code/main.c b/source_code/main.c index 1a9a3f1..e217766 100644 --- a/source_code/main.c +++ b/source_code/main.c @@ -159,7 +159,7 @@ static ULONG get_stack_size(void); static void stack_usage_init(struct StackSwapStruct * stk); static ULONG stack_usage_exit(const struct StackSwapStruct * stk); static LONG CVSPrintf(const TEXT * format_string, APTR args); -static void VSPrintf(STRPTR buffer, const TEXT * formatString, APTR args); +static int LocalVSNPrintf(STRPTR buffer, int limit, const TEXT * formatString, APTR args); static void cleanup(void); static BOOL setup(const TEXT * program_name, const TEXT * service, const TEXT * workgroup, const TEXT * username, STRPTR opt_password, BOOL opt_changecase, const TEXT * opt_clientname, const TEXT * opt_servername, int opt_cachesize, int opt_max_transmit, int opt_timeout, LONG *opt_time_zone_offset, LONG *opt_dst_offset, BOOL opt_raw_smb, BOOL opt_unicode, BOOL opt_prefer_core_protocol, BOOL opt_session_setup_delay_unicode, BOOL opt_write_behind, const TEXT * device_name, const TEXT * volume_name, const TEXT * translation_file); static void file_system_handler(BOOL raise_priority, const TEXT * device_name, const TEXT * volume_name, const TEXT * service_name); @@ -253,6 +253,8 @@ static TEXT map_smb_to_amiga_name[256]; static LONG MaxNameLen; +static BOOL file_system_disabled; + /****************************************************************************/ #if defined(__amigaos4__) @@ -832,12 +834,16 @@ main(void) if(str != NULL) { + int size; + /* Set up the name of the program, as it will be * displayed in error requesters. */ - NewProgramName = AllocVec(strlen(WBStartup->sm_ArgList[0].wa_Name) + strlen(" ''") + strlen(str)+1,MEMF_ANY|MEMF_PUBLIC); + size = strlen(WBStartup->sm_ArgList[0].wa_Name) + strlen(" ''") + strlen(str)+1; + + NewProgramName = AllocVec(size,MEMF_ANY|MEMF_PUBLIC); if(NewProgramName != NULL) - SPrintf(NewProgramName,"%s '%s'",WBStartup->sm_ArgList[0].wa_Name,str); + LocalSNPrintf(NewProgramName,size,"%s '%s'",WBStartup->sm_ArgList[0].wa_Name,str); } str = FindToolType(Icon->do_ToolTypes,"MAXNAMELEN"); @@ -1016,13 +1022,16 @@ main(void) if(args.Service != NULL) { const TEXT * name = FilePart(program_name); + int size; /* Set up the name of the program, as it will be * displayed in the proces status list. */ - NewProgramName = AllocVec(strlen(name) + strlen(" ''") + strlen(args.Service)+1,MEMF_ANY|MEMF_PUBLIC); + size = strlen(name) + strlen(" ''") + strlen(args.Service)+1; + + NewProgramName = AllocVec(size,MEMF_ANY|MEMF_PUBLIC); if(NewProgramName != NULL) - SPrintf(NewProgramName,"%s '%s'",name,args.Service); + LocalSNPrintf(NewProgramName,size,"%s '%s'",name,args.Service); } if(args.MaxNameLen != NULL) @@ -1639,7 +1648,7 @@ add_error_message(const TEXT * fmt,APTR args) { STRPTR msg = (STRPTR)(mn + 1); - VSPrintf(msg,fmt,args); + LocalVSNPrintf(msg,size,fmt,args); AddTail((struct List *)&ErrorList,(struct Node *)mn); } @@ -1948,6 +1957,7 @@ tm_to_seconds(const struct tm * const tm) struct FormatContext { TEXT * fc_Buffer; + int fc_Limit; int fc_Size; }; @@ -1959,7 +1969,7 @@ CountChar(REG(a3,struct FormatContext * fc)) fc->fc_Size++; } -/* Count the number of characters SPrintf() would put into a string. */ +/* Count the number of characters LocalSNPrintf() would put into a string. */ static LONG CVSPrintf(const TEXT * format_string,APTR args) { @@ -1977,37 +1987,51 @@ CVSPrintf(const TEXT * format_string,APTR args) static void ASM StuffChar(REG(d0,TEXT c),REG(a3,struct FormatContext * fc)) { - (*fc->fc_Buffer++) = c; + if(fc->fc_Limit > 0) + { + (*fc->fc_Buffer++) = c; + + fc->fc_Size++; + + fc->fc_Limit--; + } } -static void -VSPrintf(STRPTR buffer, const TEXT * formatString, APTR args) +static int +LocalVSNPrintf(STRPTR buffer, int limit, const TEXT * formatString, APTR args) { struct FormatContext fc; - fc.fc_Buffer = buffer; + fc.fc_Buffer = buffer; + fc.fc_Limit = limit-1; + fc.fc_Size = 0; RawDoFmt(formatString,args,(void (*)())StuffChar,&fc); + + if(limit > 0) + (*fc.fc_Buffer) = '\0'; + + return(fc.fc_Size); } /****************************************************************************/ /* Format a string for output. */ void VARARGS68K -SPrintf(STRPTR buffer, const TEXT * formatString,...) +LocalSNPrintf(STRPTR buffer, int limit, const TEXT * formatString,...) { va_list varArgs; #if defined(__amigaos4__) { va_startlinear(varArgs,formatString); - VSPrintf(buffer,formatString,va_getlinearva(varArgs,APTR)); + LocalVSNPrintf(buffer,limit,formatString,va_getlinearva(varArgs,APTR)); va_end(varArgs); } #else { va_start(varArgs,formatString); - VSPrintf(buffer,formatString,varArgs); + LocalVSNPrintf(buffer,limit,formatString,varArgs); va_end(varArgs); } #endif /* __amigaos4__ */ @@ -2983,17 +3007,55 @@ validate_amigados_file_name(const TEXT * name,int len) /****************************************************************************/ +/* Pick up all the DOS packets waiting to be processed and + * return them with an error, claiming that the packet cannot + * be processed. + */ +static void +reject_all_pending_packets(struct MsgPort * port) +{ + struct DosPacket * dp; + struct Message * mn; + LONG result; + + while((mn = GetMsg(port)) != NULL) + { + SHOWMSG("returning pending packet"); + + dp = (struct DosPacket *)mn->mn_Node.ln_Name; + + switch(dp->dp_Action) + { + case ACTION_READ_LINK: + case ACTION_SEEK: + case ACTION_SET_FILE_SIZE: + case ACTION_READ: + case ACTION_WRITE: + + result = -1; + break; + + default: + + result = DOSFALSE; + break; + } + + ReplyPkt(dp,result,ERROR_ACTION_NOT_KNOWN); + } +} + +/****************************************************************************/ + /* Remove a DosList entry using the proper protocols. Note that * this function can fail! */ static BOOL really_remove_dosentry(struct DosList * entry) { - struct DosPacket * dp; - struct Message * mn; struct MsgPort * port; struct DosList * dl; - BOOL result = FALSE; + BOOL success = FALSE; int kind,i; ENTER(); @@ -3016,7 +3078,7 @@ really_remove_dosentry(struct DosList * entry) dl = AttemptLockDosList(LDF_WRITE|kind); /* Workaround for dos.library bug... */ - if(((ULONG)dl) <= 1) + if(((ULONG)dl) == 1) dl = NULL; if(dl != NULL) @@ -3027,28 +3089,21 @@ really_remove_dosentry(struct DosList * entry) UnLockDosList(LDF_WRITE|kind); - result = TRUE; + success = TRUE; break; } - while((mn = GetMsg(port)) != NULL) - { - SHOWMSG("returning pending packet"); - - dp = (struct DosPacket *)mn->mn_Node.ln_Name; - - ReplyPkt(dp,(dp->dp_Action == ACTION_READ_LINK) ? -1 : DOSFALSE,ERROR_ACTION_NOT_KNOWN); - } + reject_all_pending_packets(port); Delay(TICKS_PER_SECOND / 10); } - if(NOT result) + if(NO success) SHOWMSG("that didn't work"); - RETURN(result); - return(result); + RETURN(success); + return(success); } /****************************************************************************/ @@ -3142,18 +3197,10 @@ cleanup(void) if(FileSystemPort != NULL) { - struct DosPacket * dp; - struct Message * mn; - SHOWMSG("returning all pending packets"); /* Return all queued packets; there should be none, though. */ - while((mn = GetMsg(FileSystemPort)) != NULL) - { - dp = (struct DosPacket *)mn->mn_Node.ln_Name; - - ReplyPkt(dp,(dp->dp_Action == ACTION_READ_LINK) ? -1 : DOSFALSE,ERROR_ACTION_NOT_KNOWN); - } + reject_all_pending_packets(FileSystemPort); SHOWMSG("done"); @@ -3512,7 +3559,7 @@ setup( /* Try to find a unique device name out of 100 possible options. */ for(i = 0 ; i < 100 ; i++) { - SPrintf(name,"SMBFS%ld",i); + LocalSNPrintf(name,sizeof(name),"SMBFS%ld",i); device_exists = (BOOL)(FindDosEntry(dl,name,LDF_DEVICES) != NULL); if(NOT device_exists) @@ -3596,7 +3643,7 @@ setup( DeviceNodeAdded = TRUE; } - /* Note: we always need the volume node to make some file + /* Note: We always need the volume node to make some file * system operations safe (e.g. Lock()), but we may * not always need to make it visible. */ @@ -3718,7 +3765,7 @@ escape_name(const TEXT * name) default: - SPrintf(hex_code,"\\x%02lx",c); + LocalSNPrintf(hex_code,sizeof(hex_code),"\\x%02lx",c); str = hex_code; l = 4; @@ -3742,7 +3789,7 @@ escape_name(const TEXT * name) break; } - SPrintf(hex_code,"\\x%02lx",c); + LocalSNPrintf(hex_code,sizeof(hex_code),"\\x%02lx",c); memcpy(&buffer[len],hex_code,4); len += 4; @@ -4310,7 +4357,8 @@ get_base_name(const TEXT * path_name,int path_name_len) /* Find the parent directory of a file or directory. This strips off the * last part of the name, e.g. translating "\foo" into "\" and "\foo\bar" - * into "\foo". There is no parent for the root directory ("\"). + * into "\foo". There is no parent for the root directory ("\"), which + * is signalled by setting the error code returned to ERROR_OBJECT_NOT_FOUND. */ static int get_parent_dir_name(const TEXT * name,int name_len,STRPTR * parent_name_ptr) @@ -4397,14 +4445,14 @@ get_parent_dir_name(const TEXT * name,int name_len,STRPTR * parent_name_ptr) * be modified in place and may become longer than it already is. */ static int -translate_amiga_name_to_smb_name(STRPTR name, int name_len, int name_size) +translate_amiga_name_to_smb_name(TEXT * name, int name_len, int name_size) { int error = ERROR_INVALID_COMPONENT_NAME; ASSERT( name != NULL && name_len < name_size ); /* Translate the Amiga file name using a translation table? */ - if (TranslateNames) + if(TranslateNames) { const TEXT * map = map_amiga_to_smb_name; TEXT c; @@ -4439,14 +4487,14 @@ translate_amiga_name_to_smb_name(STRPTR name, int name_len, int name_size) * in place and may become longer than it already is. */ static int -translate_smb_name_to_amiga_name(STRPTR name, int name_len, int name_size) +translate_smb_name_to_amiga_name(TEXT * name, int name_len, int name_size) { int error = ERROR_INVALID_COMPONENT_NAME; ASSERT( name != NULL && name_len < name_size ); /* Translate the name to Amiga format using a mapping table. */ - if (TranslateNames) + if(TranslateNames) { const TEXT * map = map_smb_to_amiga_name; TEXT c; @@ -4533,6 +4581,8 @@ lock_is_invalid(const struct FileLock * lock,int * error_ptr) const struct LockNode * ln; BOOL is_invalid = TRUE; + SHOWPOINTER(lock); + /* The ZERO lock is considered invalid. */ if(lock == NULL) { @@ -4586,6 +4636,8 @@ file_is_invalid(const struct FileNode * fn,int * error_ptr) int error = ERROR_INVALID_LOCK; BOOL is_invalid = TRUE; + SHOWPOINTER(fn); + if(fn == NULL) { SHOWMSG("no file node found"); @@ -4623,10 +4675,24 @@ file_is_invalid(const struct FileNode * fn,int * error_ptr) /****************************************************************************/ -/* Remove a device, volume or assignment name from the path name. If +/* Remove a device, volume or assignment name from the path name. * If necessary, the path following the ':' character will be copied * to the beginning of the string, removing it, and the name length * will be adjusted accordingly. + * + * This function is needed because the dos.library packet interface + * will usually provide a FileLock along with the complete path name + * of the file or drawer which must be interpreted relative to the + * FileLock. + * + * In the simple case this would be, for example, a FileLock on the + * "Workbench:Tools" directory and a path of name "Calculator". But + * it is also possible for the path to contain a volume name or + * assignment, e.g. a FileLock on "SYS:C" and a path name of "C:Dir". + * In the latter case the FileLock already refers to the correct + * parent directory and the device, volume or assignment must be + * removed from the path, which in this case would replace "C:Dir" + * with "Dir". */ static void remove_device_name_from_path(TEXT * name, int * name_len_ptr) @@ -4663,6 +4729,100 @@ remove_device_name_from_path(TEXT * name, int * name_len_ptr) /****************************************************************************/ +/* Check if the name of a file or drawer contains MS-DOS + * wildcard characters ("?" and "*") which may not be + * suitable for some file system operations, e.g. rename + * or delete. + */ +static BOOL +name_contains_wildcard_characters(const TEXT * name) +{ + const TEXT * file_name; + BOOL result = FALSE; + int len; + TEXT c; + int i; + + ENTER(); + + SHOWSTRING(name); + + file_name = FilePart(name); + len = strlen(file_name); + + for(i = 0 ; i < len ; i++) + { + c = file_name[i]; + + if(c == '?' || c == '*') + { + D(("found a wildcard in '%s'",name)); + + result = TRUE; + break; + } + } + + RETURN(result); + return(result); +} + +/****************************************************************************/ + +/* Try to obtain the path name stored in a FileLock which + * a file or directory name is associated with. The parent + * FileLock can be NULL, which is interpreted as being a + * 'ZERO lock' that stands in for the root directory of the + * volume. + */ +static BOOL +get_parent_name( + const struct FileLock * parent, + const struct MsgPort * user, + STRPTR * parent_name_ptr, + int * error_ptr) +{ + BOOL success = FALSE; + STRPTR name; + + ASSERT( error_ptr != NULL ); + + SHOWVALUE(parent); + + if(parent != NULL) + { + struct LockNode * ln; + + if(lock_is_invalid(parent, error_ptr)) + goto out; + + ln = (struct LockNode *)parent->fl_Key; + + D(("parent lock on '%s'", escape_name(ln->ln_FullName))); + + ln->ln_LastUser = user; + + name = ln->ln_FullName; + } + else + { + D(("parent lock on ':' (ZERO lock)")); + + name = NULL; + } + + if(parent_name_ptr != NULL) + (*parent_name_ptr) = name; + + success = TRUE; + + out: + + return(success); +} + +/****************************************************************************/ + static BPTR Action_Parent( const struct MsgPort * user, @@ -4679,7 +4839,17 @@ Action_Parent( SHOWVALUE(parent); - /* The ZERO lock's parent is the ZERO lock. Note that + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + + /* There are two kinds of locks which need to be dealt + * with. The first kind is the ZERO lock (= NULL), and + * the other is a pointer to a FileLock. + * + * The ZERO lock's parent is the ZERO lock. Note that * this is not the same thing as trying to obtain a * lock on the "/" directory, relative to the root * directory (which must fail with the error code @@ -4707,7 +4877,7 @@ Action_Parent( if(error != ERROR_OBJECT_NOT_FOUND) goto out; - /* We return the ZERO lock. */ + D(("returning ZERO lock")); } else { @@ -4734,6 +4904,12 @@ Action_Parent( ln = NULL; } } + else + { + D(("parent lock on ':' (ZERO lock)")); + + SHOWMSG("returning ZERO lock"); + } error = OK; @@ -4760,25 +4936,31 @@ Action_DeleteObject( LONG result = DOSFALSE; STRPTR full_name = NULL; smba_file_t * file = NULL; - const TEXT * parent_name; + STRPTR parent_name; STRPTR full_parent_name = NULL; TEXT name[MAX_FILENAME_LEN+1]; int name_len; smba_stat_t st; - TEXT * last_name; - int last_name_len; int error; - int i; ENTER(); + D(("name = '%b'",MKBADDR(bcpl_name))); + + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(WriteProtected) { error = ERROR_DISK_WRITE_PROTECTED; goto out; } - D(("name = '%b'",MKBADDR(bcpl_name))); + if(CANNOT get_parent_name(parent, user, &parent_name, &error)) + goto out; /* Name string, as given in the DOS packet, is in * BCPL format and needs to be converted into @@ -4787,28 +4969,6 @@ Action_DeleteObject( convert_from_bcpl_to_c_string(name,sizeof(name),bcpl_name); name_len = strlen(name); - SHOWVALUE(parent); - - if(parent != NULL) - { - struct LockNode * ln; - - if(lock_is_invalid(parent,&error)) - goto out; - - ln = (struct LockNode *)parent->fl_Key; - - D(("parent lock on '%s'", escape_name(ln->ln_FullName))); - - parent_name = ln->ln_FullName; - - ln->ln_LastUser = user; - } - else - { - parent_name = NULL; - } - /* Remove a device, volume or assignment name * from the path name. */ @@ -4819,25 +4979,19 @@ Action_DeleteObject( * the last part of the path (the name of the file * or directory) may contain the wildcard. */ - last_name = FilePart(name); - last_name_len = strlen(last_name); - - for(i = 0 ; i < last_name_len ; i++) + if(name_contains_wildcard_characters(name)) { - if(strchr("*?",last_name[i]) != NULL) - { - D(("found a wildcard in '%s'",name)); + D(("name '%s' is not safe to use with delete operation", name)); - /* Do not try to delete sets of matching files - * and drawers. We only came to delete a single - * directory entry. - */ - error = ERROR_OBJECT_NOT_FOUND; - goto out; - } + /* Do not try to delete sets of matching files + * and drawers. We only came to delete a single + * directory entry. + */ + error = ERROR_OBJECT_NOT_FOUND; + goto out; } - if (NOT ServerData->server.unicode_enabled) + if(NOT ServerData->server.unicode_enabled) { error = translate_amiga_name_to_smb_name(name,name_len,sizeof(name)); if(error != OK) @@ -4983,51 +5137,35 @@ Action_CreateDir( BPTR result = ZERO; STRPTR full_name = NULL; struct LockNode * ln = NULL; - const TEXT * parent_name; + STRPTR parent_name; smba_file_t * dir = NULL; TEXT name[MAX_FILENAME_LEN+1]; int name_len; STRPTR dir_name,base_name,temp = NULL; - TEXT * last_name; - int last_name_len; int error; - int i; ENTER(); + D(("name = '%b'",MKBADDR(bcpl_name))); + + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(WriteProtected) { error = ERROR_DISK_WRITE_PROTECTED; goto out; } - D(("name = '%b'",MKBADDR(bcpl_name))); + if(CANNOT get_parent_name(parent, user, &parent_name, &error)) + goto out; convert_from_bcpl_to_c_string(name,sizeof(name),bcpl_name); name_len = strlen(name); - SHOWVALUE(parent); - - if(parent != NULL) - { - struct LockNode * parent_ln; - - if(lock_is_invalid(parent,&error)) - goto out; - - parent_ln = (struct LockNode *)parent->fl_Key; - - D(("parent lock on '%s'", escape_name(parent_ln->ln_FullName))); - - parent_ln->ln_LastUser = user; - - parent_name = parent_ln->ln_FullName; - } - else - { - parent_name = NULL; - } - /* Remove a device, volume or assignment name * from the path name. */ @@ -5037,21 +5175,15 @@ Action_CreateDir( * name contains MS-DOS wildcard characters. This will * only end in tears later... */ - last_name = FilePart(name); - last_name_len = strlen(last_name); - - for(i = 0 ; i < last_name_len ; i++) + if(name_contains_wildcard_characters(name)) { - if(strchr("*?",last_name[i]) != NULL) - { - D(("found a wildcard in '%s'",name)); + D(("will not create a directory '%s' which contains wildcard characters", name)); - error = ERROR_INVALID_COMPONENT_NAME; - goto out; - } + error = ERROR_INVALID_COMPONENT_NAME; + goto out; } - if (NOT ServerData->server.unicode_enabled) + if(NOT ServerData->server.unicode_enabled) { error = translate_amiga_name_to_smb_name(name,name_len,sizeof(name)); if(error != OK) @@ -5149,7 +5281,7 @@ Action_LocateObject( BPTR result = ZERO; STRPTR full_name = NULL; struct LockNode * ln = NULL; - const TEXT * parent_name; + STRPTR parent_name; TEXT name[MAX_FILENAME_LEN+1]; int name_len; int error; @@ -5158,37 +5290,24 @@ Action_LocateObject( D(("name = '%b'",MKBADDR(bcpl_name))); + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + + if(CANNOT get_parent_name(parent, user, &parent_name, &error)) + goto out; + convert_from_bcpl_to_c_string(name,sizeof(name),bcpl_name); name_len = strlen(name); - SHOWVALUE(parent); - - if(parent != NULL) - { - struct LockNode * parent_ln; - - if(lock_is_invalid(parent,&error)) - goto out; - - parent_ln = (struct LockNode *)parent->fl_Key; - - D(("parent lock on '%s'", escape_name(parent_ln->ln_FullName))); - - parent_ln->ln_LastUser = user; - - parent_name = parent_ln->ln_FullName; - } - else - { - parent_name = NULL; - } - /* Remove a device, volume or assignment name * from the path name. */ remove_device_name_from_path(name, &name_len); - if (NOT ServerData->server.unicode_enabled) + if(NOT ServerData->server.unicode_enabled) { error = translate_amiga_name_to_smb_name(name,name_len,sizeof(name)); if(error != OK) @@ -5262,6 +5381,12 @@ Action_CopyDir( SHOWVALUE(lock); + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + /* Fail fast if the lock is invalid. */ if(lock != NULL && lock_is_invalid(lock,&error)) goto out; @@ -5272,6 +5397,10 @@ Action_CopyDir( D(("lock on '%s'", escape_name(key->ln_FullName))); } + else + { + D(("lock on ':' (ZERO lock)")); + } /* If a specific lock is to be duplicated, then that * better be a shared lock. @@ -5350,7 +5479,8 @@ Action_FreeLock( struct FileLock * lock, LONG * error_ptr) { - LONG result = DOSTRUE; + LONG result = DOSFALSE; + int error = OK; ENTER(); @@ -5360,12 +5490,21 @@ Action_FreeLock( * a valid lock if we are to proceed with releasing * it. */ - if(lock != NULL && NOT lock_is_invalid(lock,NULL)) + if(lock != NULL) { const struct LockNode * key; struct LockNode * found; struct LockNode * ln; + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + + if(lock_is_invalid(lock,&error)) + goto out; + found = NULL; key = (struct LockNode *)lock->fl_Key; @@ -5383,22 +5522,33 @@ Action_FreeLock( } } - if(found != NULL) + /* This should never happen. */ + if(found == NULL) { - Remove((struct Node *)found); - - smba_close(ServerData,found->ln_File); - - found->ln_Magic = 0; - - free_memory(found->ln_FullName); - free_memory(found); + error = ERROR_INVALID_LOCK; + goto out; } + + Remove((struct Node *)found); + + smba_close(ServerData,found->ln_File); + + found->ln_Magic = 0; + + free_memory(found->ln_FullName); + free_memory(found); } + else + { + D(("lock on ':' (ZERO lock)")); + } + + result = DOSTRUE; + error = OK; out: - (*error_ptr) = OK; + (*error_ptr) = error; RETURN(result); return(result); @@ -5423,6 +5573,12 @@ Action_SameLock( SHOWVALUE(lock1); SHOWVALUE(lock2); + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(lock1 != NULL) { struct LockNode * ln; @@ -5490,7 +5646,7 @@ Action_SetProtect( LONG result = DOSFALSE; STRPTR full_name = NULL; smba_file_t * file = NULL; - const TEXT * parent_name; + STRPTR parent_name; TEXT name[MAX_FILENAME_LEN+1]; smba_stat_t st; int name_len; @@ -5498,45 +5654,32 @@ Action_SetProtect( ENTER(); + D(("name = '%b'",MKBADDR(bcpl_name))); + + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(WriteProtected) { error = ERROR_DISK_WRITE_PROTECTED; goto out; } - D(("name = '%b'",MKBADDR(bcpl_name))); + if(CANNOT get_parent_name(parent, user, &parent_name, &error)) + goto out; convert_from_bcpl_to_c_string(name,sizeof(name),bcpl_name); name_len = strlen(name); - SHOWVALUE(parent); - - if(parent != NULL) - { - struct LockNode * ln; - - if(lock_is_invalid(parent,&error)) - goto out; - - ln = (struct LockNode *)parent->fl_Key; - - D(("parent lock on '%s'", escape_name(ln->ln_FullName))); - - ln->ln_LastUser = user; - - parent_name = ln->ln_FullName; - } - else - { - parent_name = NULL; - } - /* Remove a device, volume or assignment name * from the path name. */ remove_device_name_from_path(name, &name_len); - if (NOT ServerData->server.unicode_enabled) + if(NOT ServerData->server.unicode_enabled) { error = translate_amiga_name_to_smb_name(name,name_len,sizeof(name)); if(error != OK) @@ -5593,15 +5736,17 @@ Action_SetProtect( strlcpy(owner_bits, "hsparwed", sizeof(owner_bits)); + /* hspa */ for(i = 0 ; i < 4 ; i++) { - if((mask & (1 << (7 - i))) != 0) + if((mask & (1 << (7 - i))) == 0) owner_bits[i] = '-'; } + /* rwed */ for(i = 4 ; i < 8 ; i++) { - if((mask & (1 << (7 - i))) == 0) + if((mask & (1 << (7 - i))) != 0) owner_bits[i] = '-'; } @@ -5624,7 +5769,7 @@ Action_SetProtect( /* Careful: the 'archive' attribute has exactly the opposite * meaning in the Amiga and the SMB worlds. */ - st.is_changed_since_last_archive = ((mask & FIBF_ARCHIVE) == 0); + st.was_changed_since_last_archive = ((mask & FIBF_ARCHIVE) == 0); if(smba_setattr(file,&st,NULL,&error) < 0) { @@ -5658,7 +5803,6 @@ Action_RenameObject( const void * destination_bcpl_name, LONG * error_ptr) { - struct LockNode * ln; LONG result = DOSFALSE; STRPTR full_source_name = NULL; STRPTR full_destination_name = NULL; @@ -5666,47 +5810,32 @@ Action_RenameObject( STRPTR parent_destination_name = NULL; TEXT name[MAX_FILENAME_LEN+1]; int name_len; - const TEXT * parent_name; - TEXT * last_name; - int last_name_len; + STRPTR parent_name; int error; - int i; ENTER(); + D(("source name = '%b'",MKBADDR(source_bcpl_name))); + D(("destination name = '%b'",MKBADDR(destination_bcpl_name))); + + SHOWVALUE(source_lock); + SHOWVALUE(destination_lock); + + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(WriteProtected) { error = ERROR_DISK_WRITE_PROTECTED; goto out; } - SHOWVALUE(source_lock); - SHOWVALUE(destination_lock); - - D(("source name = '%b'",MKBADDR(source_bcpl_name))); - D(("destination name = '%b'",MKBADDR(destination_bcpl_name))); - convert_from_bcpl_to_c_string(name,sizeof(name),source_bcpl_name); name_len = strlen(name); - if(source_lock != NULL) - { - if(lock_is_invalid(source_lock,&error)) - goto out; - - ln = (struct LockNode *)source_lock->fl_Key; - - D(("source lock on '%s'", escape_name(ln->ln_FullName))); - - ln->ln_LastUser = user; - - parent_name = ln->ln_FullName; - } - else - { - parent_name = NULL; - } - /* Remove a device, volume or assignment name * from the path name. */ @@ -5716,31 +5845,28 @@ Action_RenameObject( * wildcards. Only the last part of the path (the name * of the file or directory) may contain the wildcard. */ - last_name = FilePart(name); - last_name_len = strlen(last_name); - - for(i = 0 ; i < last_name_len ; i++) + if(name_contains_wildcard_characters(name)) { - if(strchr("*?",last_name[i]) != NULL) - { - D(("found a wildcard in the source path '%s'",name)); + D(("found a wildcard in the source path '%s'; this is unsafe to use with the rename operation",name)); - /* Do not rename/move sets of matching files and - * directories. We only came to rename/move a - * single directory entry. - */ - error = ERROR_OBJECT_NOT_FOUND; - goto out; - } + /* Do not rename/move sets of matching files and + * directories. We only came to rename/move a + * single directory entry. + */ + error = ERROR_OBJECT_NOT_FOUND; + goto out; } - if (NOT ServerData->server.unicode_enabled) + if(NOT ServerData->server.unicode_enabled) { error = translate_amiga_name_to_smb_name(name,name_len,sizeof(name)); if(error != OK) goto out; } + if(CANNOT get_parent_name(source_lock, user, &parent_name, &error)) + goto out; + error = build_full_path_name(parent_name,name,&full_source_name); if(error != OK) goto out; @@ -5759,54 +5885,33 @@ Action_RenameObject( convert_from_bcpl_to_c_string(name,sizeof(name),destination_bcpl_name); name_len = strlen(name); - if(destination_lock != NULL) - { - if(lock_is_invalid(destination_lock,&error)) - goto out; - - ln = (struct LockNode *)destination_lock->fl_Key; - - D(("destination lock on '%s'", escape_name(ln->ln_FullName))); - - ln->ln_LastUser = user; - - parent_name = ln->ln_FullName; - } - else - { - parent_name = NULL; - } - /* Remove a device, volume or assignment name * from the path name. */ remove_device_name_from_path(name, &name_len); - last_name = FilePart(name); - last_name_len = strlen(last_name); - - for(i = 0 ; i < last_name_len ; i++) + if(name_contains_wildcard_characters(name)) { - if(strchr("*?",last_name[i]) != NULL) - { - D(("found a wildcard in the destination path '%s'",name)); + D(("found a wildcard in the destination path '%s'; this is unsafe to use with the rename operation",name)); - /* Do not allow the destination name to contain - * MS-DOS wildcard characters. This will only end - * in tears later... - */ - error = ERROR_INVALID_COMPONENT_NAME; - goto out; - } + /* Do not allow the destination name to contain + * MS-DOS wildcard characters. This will only end + * in tears later... + */ + error = ERROR_INVALID_COMPONENT_NAME; + goto out; } - if (NOT ServerData->server.unicode_enabled) + if(NOT ServerData->server.unicode_enabled) { error = translate_amiga_name_to_smb_name(name,name_len,sizeof(name)); if(error != OK) goto out; } + if(CANNOT get_parent_name(destination_lock, user, &parent_name, &error)) + goto out; + error = build_full_path_name(parent_name,name,&full_destination_name); if(error != OK) goto out; @@ -5882,66 +5987,73 @@ Action_DiskInfo( LONG * error_ptr) { LONG result = DOSTRUE; - LONG block_size; - LONG num_blocks; - LONG num_blocks_free; - int error; + int error = OK; ENTER(); memset(id,0,sizeof(*id)); - if(WriteProtected) - id->id_DiskState = ID_WRITE_PROTECTED; - else - id->id_DiskState = ID_VALIDATED; + /* These defaults (no disk present) will have to do until + * we know better... + */ + id->id_NumBlocks = 1; + id->id_NumBlocksUsed = 1; + id->id_BytesPerBlock = 512; + id->id_DiskType = ID_NO_DISK_PRESENT; + id->id_DiskState = ID_WRITE_PROTECTED; - if(smba_statfs(ServerData,&block_size,&num_blocks,&num_blocks_free,&error) >= 0) + if(NOT file_system_disabled) { - SHOWMSG("got the disk data"); - SHOWVALUE(block_size); - SHOWVALUE(num_blocks); - SHOWVALUE(num_blocks_free); + LONG num_blocks_free; + LONG num_blocks; + LONG block_size; - /* Pretend that the block size is 512 bytes, if not provided. */ - if(block_size <= 0) - block_size = 512; - - if (block_size < 512) + if(smba_statfs(ServerData,&block_size,&num_blocks,&num_blocks_free,&error) >= 0) { - num_blocks /= (512 / block_size); - num_blocks_free /= (512 / block_size); + if(NOT WriteProtected) + id->id_DiskState = ID_VALIDATED; + + SHOWMSG("got the disk data"); + SHOWVALUE(block_size); + SHOWVALUE(num_blocks); + SHOWVALUE(num_blocks_free); + + /* Pretend that the block size is 512 bytes, if not provided. */ + if(block_size <= 0) + block_size = 512; + + if (block_size < 512) + { + num_blocks /= (512 / block_size); + num_blocks_free /= (512 / block_size); + } + else if (block_size > 512) + { + num_blocks *= (block_size / 512); + num_blocks_free *= (block_size / 512); + } + + id->id_NumBlocks = num_blocks; + id->id_NumBlocksUsed = num_blocks - num_blocks_free; + id->id_BytesPerBlock = 512; + id->id_DiskType = ID_DOS_DISK; + id->id_VolumeNode = MKBADDR(VolumeNode); + id->id_InUse = NOT (IsListEmpty((struct List *)&FileList) && IsListEmpty((struct List *)&LockList)); + + if(id->id_NumBlocks == 0) + id->id_NumBlocks = 1; + + if(id->id_NumBlocksUsed == 0) + id->id_NumBlocksUsed = 1; } - else if (block_size > 512) + else { - num_blocks *= (block_size / 512); - num_blocks_free *= (block_size / 512); + SHOWMSG("could not get any disk data"); + + error = map_errno_to_ioerr(error); + + result = DOSFALSE; } - - id->id_NumBlocks = num_blocks; - id->id_NumBlocksUsed = num_blocks - num_blocks_free; - id->id_BytesPerBlock = 512; - id->id_DiskType = ID_DOS_DISK; - id->id_VolumeNode = MKBADDR(VolumeNode); - id->id_InUse = NOT (IsListEmpty((struct List *)&FileList) && IsListEmpty((struct List *)&LockList)); - - if(id->id_NumBlocks == 0) - id->id_NumBlocks = 1; - - if(id->id_NumBlocksUsed == 0) - id->id_NumBlocksUsed = 1; - } - else - { - SHOWMSG("could not get any disk data"); - - id->id_NumBlocks = 1; - id->id_NumBlocksUsed = 1; - id->id_BytesPerBlock = 512; - id->id_DiskType = ID_NO_DISK_PRESENT; - - error = map_errno_to_ioerr(error); - result = DOSFALSE; } SHOWVALUE(id->id_NumBlocks); @@ -5971,24 +6083,17 @@ Action_Info( SHOWVALUE(lock); + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + /* We need to check if the lock matches the volume node. However, * a ZERO lock is valid, too. */ - if(lock != NULL) - { - struct LockNode * ln; - - if(lock_is_invalid(lock, &error)) - goto out; - - ln = (struct LockNode *)lock->fl_Key; - - SHOWPOINTER(ln->ln_FullName); - - D(("lock on '%s'", escape_name(ln->ln_FullName))); - - ln->ln_LastUser = user; - } + if(CANNOT get_parent_name(lock, user, NULL, &error)) + goto out; result = Action_DiskInfo(id,error_ptr); @@ -6021,6 +6126,12 @@ Action_ExamineObject( fib->fib_DiskKey = -1; + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + /* If the ZERO lock is involved, it stands in for the * root directory. Otherwise it might be a lock on a * file or directory. @@ -6147,9 +6258,9 @@ Action_ExamineObject( /* Careful: the 'archive' attribute has exactly the opposite * meaning in the Amiga and the SMB worlds. */ - D(("is changed since last_archive = %s",st.is_changed_since_last_archive ? "yes" : "no")); + D(("was changed since last_archive = %s",st.was_changed_since_last_archive ? "yes" : "no")); - if(NOT st.is_changed_since_last_archive) + if(NOT st.was_changed_since_last_archive) fib->fib_Protection |= FIBF_ARCHIVE; D(("is directory = %s",st.is_dir ? "yes" : "no")); @@ -6159,6 +6270,10 @@ Action_ExamineObject( fib->fib_DiskKey = 0; } } + else + { + D(("lock on ':' (ZERO lock)")); + } /* So this is actually the root directory? */ if(is_root_directory) @@ -6393,7 +6508,7 @@ dir_scan_callback_func_exnext( * meaning in the Amiga (= was archived) and the SMB * worlds (= needs to be archived), respectively. */ - if(NOT st->is_changed_since_last_archive) + if(NOT st->was_changed_since_last_archive) fib->fib_Protection |= FIBF_ARCHIVE; /* If modification time is 0 use creation time instead (cyfm 2009-03-18). */ @@ -6460,6 +6575,14 @@ Action_ExamineNext( SHOWVALUE(lock); + if(file_system_disabled) + { + fib->fib_DiskKey = -1; + + error = ERROR_NO_DISK; + goto out; + } + if(lock_is_invalid(lock,&error)) { fib->fib_DiskKey = -1; @@ -6606,13 +6729,13 @@ dir_scan_callback_func_exall( /* Skip file and drawer names that we wouldn't be * able to handle in the first place. */ - if (NOT name_is_acceptable(name)) + if(NOT name_is_acceptable(name)) { D((" name is not acceptable")); goto out; } - if (st->is_hidden && OmitHidden) + if(st->is_hidden && OmitHidden) { D((" ignoring hidden directory entry")); goto out; @@ -6620,7 +6743,7 @@ dir_scan_callback_func_exall( name_len = strlen(name); - if (NOT ServerData->server.unicode_enabled) + if(NOT ServerData->server.unicode_enabled) { if(name_len >= (int)sizeof(translated_name)) { @@ -6756,9 +6879,9 @@ dir_scan_callback_func_exall( /* Careful: the 'archive' attribute has exactly the opposite * meaning in the Amiga and the SMB worlds. */ - D((" is changed since last_archive = %s",st->is_changed_since_last_archive ? "yes" : "no")); + D((" was changed since last_archive = %s",st->was_changed_since_last_archive ? "yes" : "no")); - if(NOT st->is_changed_since_last_archive) + if(NOT st->was_changed_since_last_archive) ed->ed_Prot |= FIBF_ARCHIVE; D((" protection=0x%08lx", ed->ed_Prot)); @@ -6830,14 +6953,21 @@ dir_scan_callback_func_exall( { SHOWMSG(" checking if match function accepts the entry"); - /* NOTE: the order of the parameters passed to the match hook - * function can be somewhat confusing. For standard - * hook functions, the order of the parameters and the - * registers they go into is hook=A0, object=A2, - * message=A1. However, the documentation for the 'ExAll()' - * function always lists them in ascending order, that is + /* Note: The order of the parameters passed to the match hook + * function can be somewhat confusing. + * + * For standard hook functions, the order of the parameters + * and the registers they go into is hook=A0, object=A2, + * message=A1. + * + * However, the documentation for the 'ExAll()' function + * always lists them in ascending order, that is * hook=A0, message=A1, object=A2, which can lead to * quite some confusion and strange errors. + * + * The parameter order which is correct for the CallHookPkt() + * function is given below: 1. match function (hook), + * 2. pointer to type, 3. pointer to ExAllData. */ if(NOT CallHookPkt(ec->ec_Control->eac_MatchFunc,&type,ed)) { @@ -6911,6 +7041,12 @@ Action_ExamineAll( eac->eac_Entries = 0; + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + /* Check if the lock is suitable. */ if(lock_is_invalid(lock, &error)) goto out; @@ -7085,7 +7221,7 @@ Action_ExamineAll( smba_readdir(ln->ln_File,offset,&ec,(smba_callback_t)dir_scan_callback_func_exall,&error); /* Did the smba_readdir() run into trouble? */ - if(error != OK) + if (error != OK) { D(("error whilst scanning (errno=%ld)", error)); @@ -7176,6 +7312,12 @@ Action_ExamineAllEnd( ENTER(); + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + /* Check if the lock is suitable. */ if(lock_is_invalid(lock,&error)) goto out; @@ -7214,21 +7356,17 @@ Action_Find( STRPTR parent_path = NULL; STRPTR full_name = NULL; struct FileNode * fn = NULL; - const TEXT * parent_name; + STRPTR parent_name; TEXT name[MAX_FILENAME_LEN+1]; - BOOL name_contains_wildcard_characters = FALSE; + BOOL wildcard_characters_found_in_name = FALSE; int name_len; BOOL create_new_file = FALSE; STRPTR temp = NULL; smba_stat_t st; int error; - int i; ENTER(); - convert_from_bcpl_to_c_string(name,sizeof(name),bcpl_name); - name_len = strlen(name); - switch(action) { case ACTION_FINDINPUT: @@ -7249,28 +7387,18 @@ Action_Find( break; } - SHOWVALUE(parent); - - if(parent != NULL) + if(file_system_disabled) { - struct LockNode * ln; - - if(lock_is_invalid(parent,&error)) - goto out; - - ln = (struct LockNode *)parent->fl_Key; - - D(("parent lock on '%s'", escape_name(ln->ln_FullName))); - - ln->ln_LastUser = user; - - parent_name = ln->ln_FullName; - } - else - { - parent_name = NULL; + error = ERROR_NO_DISK; + goto out; } + if(CANNOT get_parent_name(parent, user, &parent_name, &error)) + goto out; + + convert_from_bcpl_to_c_string(name,sizeof(name),bcpl_name); + name_len = strlen(name); + /* Remove a device, volume or assignment name * from the path name. */ @@ -7281,36 +7409,26 @@ Action_Find( */ if(action != ACTION_FINDINPUT) { - const TEXT * last_name; - int last_name_len; - - last_name = FilePart(name); - last_name_len = strlen(last_name); - - for(i = 0 ; i < last_name_len ; i++) + if(name_contains_wildcard_characters(name)) { - if(strchr("*?",last_name[i]) != NULL) + if(action == ACTION_FINDOUTPUT) { - D(("found a wildcard in '%s'",name)); + D(("will not create a file with wildcard characters in its name")); - if(action == ACTION_FINDOUTPUT) - { - error = ERROR_INVALID_COMPONENT_NAME; - goto out; - } - - /* We don't know yet if MODE_READWRITE will - * succeed in opening the file whose name - * contains wildcard characters. This will - * be checked later, if needed. - */ - name_contains_wildcard_characters = TRUE; - break; + error = ERROR_INVALID_COMPONENT_NAME; + goto out; } + + /* We don't know yet if MODE_READWRITE will + * succeed in opening the file whose name + * contains wildcard characters. This will + * be checked later, if needed. + */ + wildcard_characters_found_in_name = TRUE; } } - if (NOT ServerData->server.unicode_enabled) + if(NOT ServerData->server.unicode_enabled) { error = translate_amiga_name_to_smb_name(name,name_len,sizeof(name)); if(error != OK) @@ -7391,7 +7509,7 @@ Action_Find( * MS-DOS wildcard characters. This will only * end in tears later... */ - if(name_contains_wildcard_characters) + if(wildcard_characters_found_in_name) { error = ERROR_INVALID_COMPONENT_NAME; goto out; @@ -7501,6 +7619,12 @@ Action_Read( ENTER(); + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(file_is_invalid(fn,&error)) goto out; @@ -7544,6 +7668,12 @@ Action_Write( ENTER(); + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(WriteProtected) { error = ERROR_DISK_WRITE_PROTECTED; @@ -7591,6 +7721,12 @@ Action_End( struct FileNode * found; int error = OK; + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(file_is_invalid(which_fn,&error)) goto out; @@ -7653,6 +7789,12 @@ Action_Seek( ENTER(); + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(file_is_invalid(fn,&error)) goto out; @@ -7752,6 +7894,12 @@ Action_SetFileSize( ENTER(); + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(WriteProtected) { error = ERROR_DISK_WRITE_PROTECTED; @@ -7862,7 +8010,7 @@ Action_SetDate( LONG result = DOSFALSE; STRPTR full_name = NULL; smba_file_t * file = NULL; - const TEXT * parent_name; + STRPTR parent_name; TEXT name[MAX_FILENAME_LEN+1]; smba_stat_t st; LONG seconds; @@ -7871,45 +8019,32 @@ Action_SetDate( ENTER(); + D(("name = '%b'",MKBADDR(bcpl_name))); + + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(WriteProtected) { error = ERROR_DISK_WRITE_PROTECTED; goto out; } - SHOWVALUE(parent); - - D(("name = '%b'",MKBADDR(bcpl_name))); + if(CANNOT get_parent_name(parent, user, &parent_name, &error)) + goto out; convert_from_bcpl_to_c_string(name,sizeof(name),bcpl_name); name_len = strlen(name); - if(parent != NULL) - { - struct LockNode * ln; - - if(lock_is_invalid(parent,&error)) - goto out; - - ln = (struct LockNode *)parent->fl_Key; - - D(("parent lock on '%s'", escape_name(ln->ln_FullName))); - - ln->ln_LastUser = user; - - parent_name = ln->ln_FullName; - } - else - { - parent_name = NULL; - } - /* Remove a device, volume or assignment name * from the path name. */ remove_device_name_from_path(name, &name_len); - if (NOT ServerData->server.unicode_enabled) + if(NOT ServerData->server.unicode_enabled) { error = translate_amiga_name_to_smb_name(name,name_len,sizeof(name)); if(error != OK) @@ -8022,6 +8157,12 @@ Action_ExamineFH( fib->fib_DiskKey = -1; + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(file_is_invalid(fn,&error)) goto out; @@ -8103,9 +8244,9 @@ Action_ExamineFH( /* Careful: the 'archive' attribute has exactly the opposite * meaning in the Amiga and the SMB worlds. */ - D(("is changed since last_archive = %s",st.is_changed_since_last_archive ? "yes" : "no")); + D(("was changed since last_archive = %s",st.was_changed_since_last_archive ? "yes" : "no")); - if(NOT st.is_changed_since_last_archive) + if(NOT st.was_changed_since_last_archive) fib->fib_Protection |= FIBF_ARCHIVE; /* If modification time is 0 use creation time instead (cyfm 2009-03-18). */ @@ -8170,6 +8311,12 @@ Action_ParentFH( ENTER(); + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(file_is_invalid(fn,&error)) goto out; @@ -8227,6 +8374,12 @@ Action_CopyDirFH( ENTER(); + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(file_is_invalid(fn,&error)) goto out; @@ -8254,7 +8407,7 @@ Action_CopyDirFH( D(("full_name = '%s'",escape_name(full_name))); - if (smba_open(ServerData,full_name,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0) + if(smba_open(ServerData,full_name,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0) { error = map_errno_to_ioerr(error); goto out; @@ -8295,6 +8448,12 @@ Action_FHFromLock( SHOWVALUE(fl); + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(lock_is_invalid(fl,&error)) goto out; @@ -8355,6 +8514,12 @@ Action_RenameDisk( ENTER(); + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(WriteProtected) { error = ERROR_DISK_WRITE_PROTECTED; @@ -8440,8 +8605,12 @@ Action_CurrentVolume( goto out; } + /* This is in support of the "Please insert volume XXXin any drive" + * requester. Not that it should be needed, but you never know... + */ + result = MKBADDR(DeviceNode); - error = 0; + error = 0; /* This is actually the unit number. */ out: @@ -8471,15 +8640,28 @@ Action_ChangeMode( ENTER(); + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + /* Bug compatibility: the ChangeMode() autodocs used to suggest that the * 'new_mode' parameter should contain the new access mode without actually * explaining what that mode should be. Consequently, no two file systems - * out of three are implementing this packet the same way. Some allow - * SHARED_LOCK/EXCLUSIVE_LOCK for both file handles and file locks, some - * try to allow MODE_OLDFILE/MODE_READWRITE/MODE_NEWFILE for file handles - * but really assume that it should be SHARED_LOCK/EXCLUSIVE_LOCK with - * hilarious/tragic consequences. The only file system which sort of got + * out of three are implementing this packet the same way. + * + * Some file systems allow SHARED_LOCK/EXCLUSIVE_LOCK for both file handles + * and file locks, some try to allow MODE_OLDFILE/MODE_READWRITE/MODE_NEWFILE + * for file handles but really assume that it should be SHARED_LOCK/EXCLUSIVE_LOCK + * with hilarious/tragic consequences. The only file system which sort of got * this right was ram-handler. + * + * We accept MODE_OLDFILE, MODE_READWRITE and MODE_NEWFILE for files, as well + * as SHARED_LOCK and EXCLUSIVE_LOCK. This works because these five modes + * are represented by different numbers. + * + * For locks we only accept SHARED_LOCK and EXCLUSIVE_LOCK. */ if(type == CHANGE_FH) { @@ -8592,6 +8774,12 @@ Action_WriteProtect( ENTER(); + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(flag == DOSFALSE) { if(WriteProtected) @@ -8679,52 +8867,39 @@ Action_SetComment( LONG result = DOSFALSE; STRPTR full_name = NULL; smba_file_t * file = NULL; - const TEXT * parent_name; + STRPTR parent_name; TEXT name[MAX_FILENAME_LEN+1]; int name_len; int error; ENTER(); + D(("name = '%b', comment = '%s'",MKBADDR(bcpl_name),MKBADDR(bcpl_comment))); + + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(WriteProtected) { error = ERROR_DISK_WRITE_PROTECTED; goto out; } - D(("name = '%b', comment = '%s'",MKBADDR(bcpl_name),MKBADDR(bcpl_comment))); + if(CANNOT get_parent_name(parent, user, &parent_name, &error)) + goto out; convert_from_bcpl_to_c_string(name,sizeof(name),bcpl_name); name_len = strlen(name); - SHOWVALUE(parent); - - if(parent != NULL) - { - struct LockNode * ln; - - if(lock_is_invalid(parent,&error)) - goto out; - - ln = (struct LockNode *)parent->fl_Key; - - D(("parent lock on '%s'", escape_name(ln->ln_FullName))); - - ln->ln_LastUser = user; - - parent_name = ln->ln_FullName; - } - else - { - parent_name = NULL; - } - /* Remove a device, volume or assignment name * from the path name. */ remove_device_name_from_path(name, &name_len); - if (NOT ServerData->server.unicode_enabled) + if(NOT ServerData->server.unicode_enabled) { error = translate_amiga_name_to_smb_name(name,name_len,sizeof(name)); if(error != OK) @@ -8746,7 +8921,7 @@ Action_SetComment( D(("full_name = '%s'",escape_name(full_name))); - if (smba_open(ServerData,full_name,open_writable,open_dont_truncate,&file,&error) < 0) + if(smba_open(ServerData,full_name,open_writable,open_dont_truncate,&file,&error) < 0) { error = map_errno_to_ioerr(error); goto out; @@ -8785,42 +8960,48 @@ Action_LockRecord( ENTER(); + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(file_is_invalid(fn,&error)) goto out; D(("file opened on '%s'", escape_name(fn->fn_FullName))); /* Sanity checks... */ - if (mode < REC_EXCLUSIVE || mode > REC_SHARED_IMMED) + if(mode < REC_EXCLUSIVE || mode > REC_SHARED_IMMED) { error = ERROR_ACTION_NOT_KNOWN; goto out; } /* Invalid offset, size or integer overflow? */ - if (offset < 0 || length <= 0 || offset + length < offset) + if(offset < 0 || length <= 0 || offset + length < offset) { error = ERROR_LOCK_COLLISION; goto out; } - if ((mode == REC_SHARED) || (mode == REC_SHARED_IMMED)) + if((mode == REC_SHARED) || (mode == REC_SHARED_IMMED)) umode = 1; else umode = 0; - if ((mode == REC_SHARED_IMMED) || (mode == REC_EXCLUSIVE_IMMED)) + if((mode == REC_SHARED_IMMED) || (mode == REC_EXCLUSIVE_IMMED)) timeout = 0; - if (timeout > 0) + if(timeout > 0) { - if (timeout > 214748364) + if(timeout > 214748364) timeout = ~0UL; /* wait forever */ else timeout *= 20; /* milliseconds instead of Ticks */ } - if (smba_lockrec (fn->fn_File, offset, length, umode, 0, (long)timeout, &error) < 0) + if(smba_lockrec (fn->fn_File, offset, length, umode, 0, (long)timeout, &error) < 0) { error = map_errno_to_ioerr(error); goto out; @@ -8850,6 +9031,12 @@ Action_FreeRecord( ENTER(); + if(file_system_disabled) + { + error = ERROR_NO_DISK; + goto out; + } + if(file_is_invalid(fn,&error)) goto out; @@ -8862,7 +9049,7 @@ Action_FreeRecord( goto out; } - if (smba_lockrec (fn->fn_File, offset, length, 2, -1, 0, &error) < 0) + if(smba_lockrec (fn->fn_File, offset, length, 2, -1, 0, &error) < 0) { error = map_errno_to_ioerr(error); goto out; @@ -8892,6 +9079,7 @@ file_system_handler( int old_priority = 0; fd_set read_fds; int server_fd; + ULONG signal_mask; ULONG signals; BOOL done; @@ -8974,6 +9162,8 @@ file_system_handler( Permit(); } + signal_mask = SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F | (1UL << FileSystemPort->mp_SigBit); + FD_ZERO(&read_fds); do @@ -8988,7 +9178,7 @@ file_system_handler( /* We want to know if this socket has readable data for us. */ FD_SET(server_fd, &read_fds); - signals = SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F | (1UL << FileSystemPort->mp_SigBit); + signals = signal_mask; /* Wait for the server to send something, a signal to be received * or the next file system packet to arrive. @@ -9066,23 +9256,89 @@ file_system_handler( */ else { - signals = Wait(SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F | (1UL << FileSystemPort->mp_SigBit)); + signals = Wait(signal_mask); } + /* Stop the file system? */ if(signals & SIGBREAKF_CTRL_C) { SHOWMSG("stop signal received; trying to quit..."); Quit = TRUE; } + /* Re-enable the file system? If both disable and enable signals + * are present, we always stick with keeping the file system + * enabled. + */ + if (signals & SIGBREAKF_CTRL_E) + { + /* Note that the volume node needs to be around so that + * the Workbench and others can correctly report that + * the file system is not currently operational. + */ + if(VolumeNodeAdded && file_system_disabled) + { + SHOWMSG("re-enabling the file system"); + + file_system_disabled = FALSE; + + send_disk_change_notification(IECLASS_DISKINSERTED); + } + } + /* Disable the file system? */ + else if (signals & SIGBREAKF_CTRL_D) + { + if(VolumeNodeAdded && NOT file_system_disabled) + { + SHOWMSG("disabling the file system"); + + file_system_disabled = TRUE; + + send_disk_change_notification(IECLASS_DISKREMOVED); + } + } + if(signals & (1UL << FileSystemPort->mp_SigBit)) { + struct timeval start_time; struct DosPacket * dp; struct Message * mn; LONG res1,res2; - while((mn = GetMsg(FileSystemPort)) != NULL) + while(TRUE) { + /* Count the number of packets currently waiting to be processed. */ + #if DEBUG + { + ULONG num_packets_waiting; + struct Node * ln; + + Disable(); + + num_packets_waiting = 0; + + for(ln = FileSystemPort->mp_MsgList.lh_Head ; + ln->ln_Succ != NULL ; + ln = ln->ln_Succ) + { + num_packets_waiting++; + } + + Enable(); + + if (num_packets_waiting > 1) + D(("%lu packets are waiting to be processed", num_packets_waiting)); + else if (num_packets_waiting == 1) + D(("1 packet is waiting to be processed")); + else + D(("no packet is waiting to be processed")); + } + #endif /* DEBUG */ + + mn = GetMsg(FileSystemPort); + if(mn == NULL) + break; + dp = (struct DosPacket *)mn->mn_Node.ln_Name; #if DEBUG @@ -9185,6 +9441,13 @@ file_system_handler( } #endif /* DEBUG */ + /* We want to know how long it takes to process this packet. */ + #if DEBUG + { + GetSysTime((APTR)&start_time); + } + #endif /* DEBUG */ + res2 = 0; switch(dp->dp_Action) @@ -9251,19 +9514,22 @@ file_system_handler( case ACTION_MORE_CACHE: /* Buffer delta -> Total number of buffers */ - /* NOTE: documentation for this packet type is inconsistent; + /* Note: Documentation for this packet type is inconsistent; * in the 'good old' 1.x days 'res1' was documented as * the total number of buffers to be returned. In the * 2.x documentation it is said that 'res1' should * return the success code, with 'res2' to hold the - * total number of buffers. However, the 'AddBuffers' - * shell command doesn't work that way, and the - * dos.library implementation of 'AddBuffers()' doesn't - * work that way either. The 1.3 'AddBuffers' command - * appears to treat a zero result as failure and a - * non-zero result as success, which suggests that this - * is how the packet is supposed to work, contrary to - * what the official documentation says. + * total number of buffers. + * + * However, the 'AddBuffers' shell command doesn't work + * that way, and the dos.library implementation of + * 'AddBuffers()' doesn't work that way either. + * + * The 1.3 'AddBuffers' command appears to treat a zero + * result as failure and a non-zero result as success, + * which suggests that this is how the packet is supposed + * to work, contrary to what the official documentation + * says. */ res1 = Action_MoreCache(dp->dp_Arg1,&res2); break; @@ -9302,8 +9568,11 @@ file_system_handler( /* InfoData -> Bool */ Action_DiskInfo((struct InfoData *)BADDR(dp->dp_Arg1),&res2); + + /* This should always work. */ res1 = DOSTRUE; res2 = 0; + break; case ACTION_INFO: @@ -9327,7 +9596,10 @@ file_system_handler( case ACTION_INHIBIT: SHOWMSG("ACTION_INHIBIT"); - res1 = DOSTRUE; + + res1 = DOSFALSE; + res2 = ERROR_ACTION_NOT_KNOWN; + break; case ACTION_SET_DATE: @@ -9477,7 +9749,51 @@ file_system_handler( break; } - D(("Returning packet with res1=%ld (0x%08lx) and res2=%ld (0x%08lx)\n",res1,res1,res2,res2)); + #if DEBUG + { + struct timeval finish_time; + TEXT processing_time[30]; + + /* Figure out how long it took to process this + * packet. Because the system time may have been + * adjusted between the beginning of the processing + * and getting here, we need to make sure that time + * didn't flow backwards... + */ + GetSysTime(&finish_time); + + if(-CmpTime(&finish_time,&start_time) >= 0) + { + int l; + + SubTime(&finish_time,&start_time); + + /* Print the processing time as the number of + * seconds which have passed, without trailing + * zeroes after the decimal point (and removing the + * decimal point altogether if all trailing zeroes + * have been removed. + */ + LocalSNPrintf(processing_time,sizeof(processing_time),"%lu.%06lu", finish_time.tv_secs, finish_time.tv_micro); + + l = strlen(processing_time); + while(l > 0 && processing_time[l-1] == '0') + l--; + + if(l > 0 && processing_time[l-1] == '.') + l--; + + processing_time[l++] = 's'; + processing_time[l] = '\0'; + } + else + { + strlcpy(processing_time,"unknown",sizeof(processing_time)); + } + + D(("Returning packet with res1=%ld (0x%08lx) and res2=%ld (0x%08lx); processing time=%s\n",res1,res1,res2,res2,processing_time)); + } + #endif /* DEBUG */ ReplyPkt(dp,res1,res2); } diff --git a/source_code/proc.c b/source_code/proc.c index 2fc27f6..6426d8e 100644 --- a/source_code/proc.c +++ b/source_code/proc.c @@ -1049,7 +1049,7 @@ smb_request_ok_with_payload ( } else { - D(("smb_request() returned %ld bytes\n", result)); + LOG(("smb_request() returned %ld bytes\n", result)); /* Return 0 for success, rather than the number of * bytes received. @@ -1234,7 +1234,7 @@ smb_proc_open (struct smb_server *server, const char *pathname, int len, int wri ENTER(); - D(("pathname = '%s'", escape_name(pathname))); + LOG(("pathname = '%s'\n", escape_name(pathname))); /* Because the original code opened every file/directory in * read/write mode, we emulate the same behaviour. Why this @@ -2745,7 +2745,7 @@ smb_decode_long_dirent (const struct smb_server *server, const char *p, struct s /* Skip directory entries whose names we cannot store. */ if(name_len >= (int)finfo->complete_path_size) { - D(("name length >= %ld (skipping it)", finfo->complete_path_size)); + LOG(("name length >= %ld (skipping it)\n", finfo->complete_path_size)); success = FALSE; break; @@ -2753,7 +2753,7 @@ smb_decode_long_dirent (const struct smb_server *server, const char *p, struct s if(name_len == 0) { - D(("name length == 0 (skipping it)")); + LOG(("name length == 0 (skipping it)\n")); success = FALSE; break; @@ -2779,7 +2779,7 @@ smb_decode_long_dirent (const struct smb_server *server, const char *p, struct s finfo->len = name_len; - D(("name = '%s', length=%ld, size=%ld",escape_name(finfo->complete_path),name_len,name_size)); + LOG(("name = '%s', length=%ld, size=%ld\n",escape_name(finfo->complete_path),name_len,name_size)); #if DEBUG { @@ -2879,7 +2879,7 @@ smb_decode_long_dirent (const struct smb_server *server, const char *p, struct s /* Skip directory entries whose names we cannot store. */ if(name_len >= (int)finfo->complete_path_size) { - D(("name length >= %ld (skipping it)", finfo->complete_path_size)); + LOG(("name length >= %ld (skipping it)\n", finfo->complete_path_size)); success = FALSE; break; @@ -2887,7 +2887,7 @@ smb_decode_long_dirent (const struct smb_server *server, const char *p, struct s if(name_len == 0) { - D(("name length == 0 (skipping it)")); + LOG(("name length == 0 (skipping it)\n")); success = FALSE; break; @@ -2905,7 +2905,7 @@ smb_decode_long_dirent (const struct smb_server *server, const char *p, struct s finfo->len = name_len; - D(("name = '%s', length=%ld, size=%ld",escape_name(finfo->complete_path),name_len,name_size)); + LOG(("name = '%s', length=%ld, size=%ld\n",escape_name(finfo->complete_path),name_len,name_size)); #if DEBUG { @@ -2934,7 +2934,7 @@ smb_decode_long_dirent (const struct smb_server *server, const char *p, struct s break; } - D(("entry_length = %ld",(*entry_length_ptr))); + LOG(("entry_length = %ld\n",(*entry_length_ptr))); RETURN(success); return(success); @@ -3192,7 +3192,7 @@ smb_proc_readdir_long (struct smb_server *server, const char *path, int fpos, in */ const int grow_size_by = 16; - D(("increasing mask; old value = %ld new value = %ld",mask_buffer_size,len + grow_size_by)); + LOG(("increasing mask; old value = %ld new value = %ld\n",mask_buffer_size,len + grow_size_by)); mask_buffer_size = len + grow_size_by; SHOWVALUE(mask_buffer_size); @@ -4709,7 +4709,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr) string_toupper(share_name); - D(("share_name = '%s'", escape_name(share_name))); + LOG(("share_name = '%s'\n", escape_name(share_name))); if(server->unicode_enabled) share_name_size = 2 * (share_name_len + 1); @@ -4814,7 +4814,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr) /* We need to allocate a larger packet buffer. */ packet_size = max_buffer_size; - D(("packet size updated to %ld bytes\n", packet_size)); + LOG(("packet size updated to %ld bytes\n", packet_size)); free (server->transmit_buffer); @@ -4843,7 +4843,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr) if(8000 <= server->mount_data.given_max_xmit && server->mount_data.given_max_xmit < (int)max_buffer_size) { max_buffer_size = server->mount_data.given_max_xmit; - D(("maximum buffer size limited to %ld bytes\n", max_buffer_size)); + LOG(("maximum buffer size limited to %ld bytes\n", max_buffer_size)); } server->max_buffer_size = max_buffer_size; diff --git a/source_code/smb_abstraction.c b/source_code/smb_abstraction.c index de4bec0..6e3f359 100644 --- a/source_code/smb_abstraction.c +++ b/source_code/smb_abstraction.c @@ -84,39 +84,39 @@ smba_connect ( if(opt_raw_smb) res->server.raw_smb = TRUE; - D(("use raw SMB = %s",opt_raw_smb ? "yes" : "no")); + LOG(("use raw SMB = %s\n",opt_raw_smb ? "yes" : "no")); /* Timeout for send/receive operations in seconds. */ res->server.timeout = timeout; - D(("send/receive/connect timeout = %ld seconds%s",timeout,timeout > 0 ? "" : " (= default timeout)")); + LOG(("send/receive/connect timeout = %ld seconds%s\n",timeout,timeout > 0 ? "" : " (= default timeout)")); /* Enable Unicode support if the server supports it, too. */ res->server.use_unicode = opt_unicode; - D(("use Unicode = %s",opt_unicode ? "yes" : "no")); + LOG(("use Unicode = %s\n",opt_unicode ? "yes" : "no")); /* Prefer SMB core protocol commands to NT1 commands, if possible. */ res->server.prefer_core_protocol = opt_prefer_core_protocol; - D(("prefer core protocol = %s",opt_prefer_core_protocol ? "yes" : "no")); + LOG(("prefer core protocol = %s\n",opt_prefer_core_protocol ? "yes" : "no")); /* Path names are case-sensitive. */ res->server.case_sensitive = opt_case_sensitive; - D(("path names are case sensitive = %s",opt_case_sensitive ? "yes" : "no")); + LOG(("path names are case sensitive = %s\n",opt_case_sensitive ? "yes" : "no")); /* Delay the use of Unicode strings during session setup. */ res->server.session_setup_delay_unicode = opt_session_setup_delay_unicode; - D(("delay use of unicode during session setup = %s",opt_session_setup_delay_unicode ? "yes" : "no")); + LOG(("delay use of unicode during session setup = %s\n",opt_session_setup_delay_unicode ? "yes" : "no")); /* Enable asynchronous SMB_COM_WRITE_RAW operations? */ res->server.write_behind = opt_write_behind; - D(("use asynchronous SMB_COM_WRITE_RAW operations = %s",opt_write_behind ? "yes" : "no")); + LOG(("use asynchronous SMB_COM_WRITE_RAW operations = %s\n",opt_write_behind ? "yes" : "no")); - D(("cache size = %ld entries", cache_size)); + LOG(("cache size = %ld entries\n", cache_size)); if(smba_setup_dircache (res,cache_size,error_ptr) < 0) { @@ -126,7 +126,7 @@ smba_connect ( strlcpy(data.workgroup_name,workgroup_name,sizeof(data.workgroup_name)); - D(("workgroup name = '%s'",workgroup_name)); + LOG(("workgroup name = '%s'\n",workgroup_name)); res->server.abstraction = res; @@ -140,9 +140,9 @@ smba_connect ( if ((s = strchr (hostname, '.')) != NULL) (*s) = '\0'; - D(("local host name = '%s'",hostname)); + LOG(("local host name = '%s'\n",hostname)); - D(("server ip address = %s",Inet_NtoA(server_ip_addr.sin_addr.s_addr))); + LOG(("server ip address = %s\n",Inet_NtoA(server_ip_addr.sin_addr.s_addr))); data.addr = server_ip_addr; @@ -209,24 +209,24 @@ smba_connect ( strlcpy (data.service, p->service, sizeof(data.service)); - D(("service = '%s'",data.service)); + LOG(("service = '%s'\n",data.service)); string_toupper (data.service); strlcpy (data.username, p->username, sizeof(data.username)); strlcpy (data.password, p->password, sizeof(data.password)); - D(("user name = '%s'",data.username)); + LOG(("user name = '%s'\n",data.username)); data.given_max_xmit = max_transmit; - D(("max transmit = %ld bytes",max_transmit)); + LOG(("max transmit = %ld bytes\n",max_transmit)); strlcpy (data.server_name, p->server_name, sizeof(data.server_name)); strlcpy (data.client_name, p->client_name, sizeof(data.client_name)); - D(("server name = '%s'",data.server_name)); - D(("client name = '%s'",data.client_name)); + LOG(("server name = '%s'\n",data.server_name)); + LOG(("client name = '%s'\n",data.client_name)); if (data.server_name[0] == '\0') { @@ -609,7 +609,7 @@ smba_read (smba_file_t * f, char *data, long len, const QUAD * const offset, int if (result < 0) goto out; - D(("read %ld bytes from offset %ld",len,offset)); + LOG(("read %ld bytes from offset %ld\n",len,offset)); /* SMB_COM_READ_ANDX supported? */ if (f->server->server.protocol >= PROTOCOL_LANMAN1 && !f->server->server.prefer_core_protocol) @@ -668,7 +668,7 @@ smba_read (smba_file_t * f, char *data, long len, const QUAD * const offset, int if(result < count) { - D(("read returned fewer characters than expected (%ld < %ld)",result,count)); + LOG(("read returned fewer characters than expected (%ld < %ld)\n",result,count)); break; } } @@ -699,7 +699,7 @@ smba_read (smba_file_t * f, char *data, long len, const QUAD * const offset, int result = smb_proc_read_raw (&f->server->server, &f->dirent, &position_quad, n, data, error_ptr); if(result <= 0) { - D(("!!! wanted to read %ld bytes, got %ld",n,result)); + LOG(("!!! wanted to read %ld bytes, got %ld\n",n,result)); break; } @@ -710,7 +710,7 @@ smba_read (smba_file_t * f, char *data, long len, const QUAD * const offset, int if(result < n) { - D(("read returned fewer characters than expected (%ld < %ld)",result,n)); + LOG(("read returned fewer characters than expected (%ld < %ld)\n",result,n)); break; } } @@ -778,7 +778,7 @@ smba_read (smba_file_t * f, char *data, long len, const QUAD * const offset, int if(result < count) { - D(("read returned fewer characters than expected (%ld < %ld)",result,count)); + LOG(("read returned fewer characters than expected (%ld < %ld)\n",result,count)); break; } } @@ -1107,11 +1107,11 @@ smba_getattr (smba_file_t * f, smba_stat_t * data, int * error_ptr) dirent = &f->dirent; - data->is_dir = (dirent->attr & SMB_FILE_ATTRIBUTE_DIRECTORY) != 0; - data->is_read_only = (dirent->attr & SMB_FILE_ATTRIBUTE_READONLY) != 0; - data->is_hidden = (dirent->attr & SMB_FILE_ATTRIBUTE_HIDDEN) != 0; - data->is_system = (dirent->attr & SMB_FILE_ATTRIBUTE_SYSTEM) != 0; - data->is_changed_since_last_archive = (dirent->attr & SMB_FILE_ATTRIBUTE_ARCHIVE) != 0; + data->is_dir = (dirent->attr & SMB_FILE_ATTRIBUTE_DIRECTORY) != 0; + data->is_read_only = (dirent->attr & SMB_FILE_ATTRIBUTE_READONLY) != 0; + data->is_hidden = (dirent->attr & SMB_FILE_ATTRIBUTE_HIDDEN) != 0; + data->is_system = (dirent->attr & SMB_FILE_ATTRIBUTE_SYSTEM) != 0; + data->was_changed_since_last_archive = (dirent->attr & SMB_FILE_ATTRIBUTE_ARCHIVE) != 0; data->size_low = dirent->size_low; data->size_high = dirent->size_high; @@ -1167,7 +1167,7 @@ smba_setattr (smba_file_t * f, const smba_stat_t * st, const QUAD * const size, else attrs &= ~SMB_FILE_ATTRIBUTE_READONLY; - if (st->is_changed_since_last_archive) + if (st->was_changed_since_last_archive) attrs |= SMB_FILE_ATTRIBUTE_ARCHIVE; else attrs &= ~SMB_FILE_ATTRIBUTE_ARCHIVE; @@ -1306,7 +1306,7 @@ smba_readdir (smba_file_t * f, int offs, void *callback_data, smba_callback_t ca data.is_read_only = (dirent->attr & SMB_FILE_ATTRIBUTE_READONLY) != 0; data.is_hidden = (dirent->attr & SMB_FILE_ATTRIBUTE_HIDDEN) != 0; data.is_system = (dirent->attr & SMB_FILE_ATTRIBUTE_SYSTEM) != 0; - data.is_changed_since_last_archive = (dirent->attr & SMB_FILE_ATTRIBUTE_ARCHIVE) != 0; + data.was_changed_since_last_archive = (dirent->attr & SMB_FILE_ATTRIBUTE_ARCHIVE) != 0; data.size_low = dirent->size_low; data.size_high = dirent->size_high; data.atime = dirent->atime; @@ -1334,7 +1334,7 @@ invalidate_dircache (struct smba_server * server) ENTER(); if(dircache->cache_for != NULL) - D(("dircache->cache_for->dirent.complete_path = '%s'", escape_name(dircache->cache_for->dirent.complete_path))); + LOG(("dircache->cache_for->dirent.complete_path = '%s'\n", escape_name(dircache->cache_for->dirent.complete_path))); else SHOWMSG("-- directory cache is empty --"); @@ -1910,7 +1910,7 @@ smba_start( */ if(SendNetBIOSStatusQuery(server_ip_address,server_name,sizeof(server_name),workgroup_name,sizeof(workgroup_name)) == 0 && server_name[0] != '\0') { - D(("server %s provided its own name '%s', with workgroup '%s'",Inet_NtoA(server_ip_address.sin_addr.s_addr),server_name,workgroup_name)); + LOG(("server %s provided its own name '%s', with workgroup '%s'\n",Inet_NtoA(server_ip_address.sin_addr.s_addr),server_name,workgroup_name)); /* No workgroup given? Use what the server told us... */ if(opt_workgroup == NULL && workgroup_name[0] != '\0') @@ -2035,7 +2035,7 @@ smba_start( par.username = username; par.password = password; - D(("server name = '%s', client name = '%s', workgroup name = '%s', user name = '%s'", server_name, client_name, workgroup, username)); + LOG(("server name = '%s', client name = '%s', workgroup name = '%s', user name = '%s'\n", server_name, client_name, workgroup, username)); if(smba_connect ( &par, diff --git a/source_code/smb_abstraction.h b/source_code/smb_abstraction.h index 6ede47e..9055955 100644 --- a/source_code/smb_abstraction.h +++ b/source_code/smb_abstraction.h @@ -67,7 +67,7 @@ typedef struct smba_stat unsigned is_read_only:1; unsigned is_hidden:1; unsigned is_system:1; - unsigned is_changed_since_last_archive:1; + unsigned was_changed_since_last_archive:1; unsigned long size_low; unsigned long size_high; diff --git a/source_code/smbfs.h b/source_code/smbfs.h index 6e22f04..ea4e72b 100644 --- a/source_code/smbfs.h +++ b/source_code/smbfs.h @@ -41,7 +41,9 @@ #define SAME (0) #define OK (0) +#define CANNOT ! #define NOT ! +#define NO ! #define NOTHING ((void)0) /****************************************************************************/ @@ -146,7 +148,7 @@ extern ULONG get_current_time(void); extern void seconds_to_tm(time_t seconds,struct tm * tm); extern void VARARGS68K report_error(const TEXT * fmt,...); extern void string_toupper(STRPTR s); -extern void VARARGS68K SPrintf(STRPTR buffer, const TEXT * formatString,...); +extern void VARARGS68K LocalSNPrintf(STRPTR buffer, int limit, const TEXT * formatString,...); extern TEXT * escape_name(const TEXT * name); extern const char * convert_quad_to_string(const QUAD * const number); diff --git a/source_code/smbfs_rev.h b/source_code/smbfs_rev.h index 3ea714e..4805d7c 100644 --- a/source_code/smbfs_rev.h +++ b/source_code/smbfs_rev.h @@ -1,6 +1,6 @@ #define VERSION 1 -#define REVISION 177 -#define DATE "27.8.2018" -#define VERS "smbfs 1.177" -#define VSTRING "smbfs 1.177 (27.8.2018)\r\n" -#define VERSTAG "\0$VER: smbfs 1.177 (27.8.2018)" +#define REVISION 181 +#define DATE "15.9.2018" +#define VERS "smbfs 1.181" +#define VSTRING "smbfs 1.181 (15.9.2018)\r\n" +#define VERSTAG "\0$VER: smbfs 1.181 (15.9.2018)" diff --git a/source_code/smbfs_rev.rev b/source_code/smbfs_rev.rev index eec4941..3b4a6e8 100644 --- a/source_code/smbfs_rev.rev +++ b/source_code/smbfs_rev.rev @@ -1 +1 @@ -177 +181 diff --git a/source_code/sock.c b/source_code/sock.c index 39098d3..2003918 100644 --- a/source_code/sock.c +++ b/source_code/sock.c @@ -149,7 +149,7 @@ smb_discard_netbios_frames(struct smb_server *server, int sock_fd, int * error_p * NetBIOS session response, but for any command * these message types are invalid. */ - D(("Invalid session header type 0x%02lx\n", netbios_session_buf[0])); + LOG(("Invalid session header type 0x%02lx\n", netbios_session_buf[0])); (*error_ptr) = error_invalid_netbios_session; @@ -165,7 +165,7 @@ smb_discard_netbios_frames(struct smb_server *server, int sock_fd, int * error_p /* The length in the NetBIOS header is the raw data length (17 bits) */ if (netbios_session_payload_size > server->transmit_buffer_allocation_size) { - D(("Received length (%ld) > max_xmit (%ld)!", netbios_session_payload_size, server->transmit_buffer_allocation_size)); + LOG(("Received length (%ld) > max_xmit (%ld)!\n", netbios_session_payload_size, server->transmit_buffer_allocation_size)); (*error_ptr) = error_message_exceeds_buffer_size; @@ -176,7 +176,7 @@ smb_discard_netbios_frames(struct smb_server *server, int sock_fd, int * error_p result = receive_all (sock_fd, server->transmit_buffer, netbios_session_payload_size, error_ptr); if (result < 0) { - D(("recv error = %ld", (*error_ptr))); + LOG(("recv error = %ld\n", (*error_ptr))); goto out; } }