rename file when using DD name - fopen

In a 'C' language LP64 compiled program, which will run in Batch, TSO and z/OS UNIX, when opening a PDS(E) member using the following notation (recommended in order to allow file disposition to be used):-
hFile = fopen("DD:CONFIG(COPY)", "w");
fclose(hFile);
I am surprised to discover that the following does not appear to work:-
rename("DD:CONFIG(COPY)","DD:CONFIG(MAIN)");
Failing as it does with an errno of ENOENT (EDC5129I No such file or directory.)
The documentation for rename says:-
The rename() function renames memory files and DASD data sets. It also renames individual members of PDSs (and PDSEs)
If instead I do:-
rename("//'MYUSER.CONFIG(COPY)'","//'MYUSER.CONFIG(MAIN)'");
the rename() works.
Alternatively if I do:-
rename("//'MYUSER.CONFIG(COPY)'","DD:CONFIG(MAIN)");
if fails with an errno of EINVAL (EDC5121I Invalid argument.)
Why does it not accept the same file name notation that is used for fopen?
The reason this is important is because the rename() cannot succeed while the PDSE is being browsed by someone. Whereas, using the DD: notation allows an fopen() for write to succeed when the PDSE is being browsed because the DISP=SHR coded on the DD name in the JCL is adopted by the fopen().
So, I suppose the real question is - how can my program rename a PDSE member in a way that will succeed when the PDSE is also being browsed by someone?

The technique required to rename a dataset is different than the technique to rename a member inside a PDS/PDSE...I'd wager that the system rename() function you're calling is just getting this wrong. In z/OS, there are lots of combinations functions like "rename()" have to handle, and it's not unusual to find some that don't work as you expect.
Certainly it's worth a call to IBM Support to see if there's something else going on here...what you're trying to do seems like it should work, so I think there's something to be said for treating it like a bug or documentation error.
Beyond that, as you suggest, you can either use the form of rename that works, or you can replace the system's rename function with something that actually works properly.
One simple way would be to create the rename() as you show it:
rename("//'MYUSER.CONFIG(COPY)'","//'MYUSER.CONFIG(MAIN)'");
You can get the DSN for a DDNAME using the fldata() function, so it's not hard to create a rename like this on the fly given an open file handle. Beware that the form of rename may allocate the file you specify with DISP=OLD, and hence cause problems if some other task has the file allocated. Also, if this is supposed to be commercial quality code, as a customer, my eyebrows would go up if I found out you needed to launch some external program because you couldn't figure out how to rename a PDS/PDSE member - but that might just be me.
The other alternative is to write your own "rename()" function...unfortunately, it most likely would need to be assembler language if you want it to be efficient. As others suggest, you might spawn off a shell, REXX or TSO command, but of course, that means creating a new process, etc etc etc just to rename the PDS/PDSE member. Keep in mind also that some of these approaches might also have issues with trying to allocate the input file with DISP=OLD.
If that's too slow for your needs, the way to do what you want is to call a small assembler routine that invokes the system STOW service against your DDNAME to do your rename. The flow would be something like this:
You'd create a 16-byte area containing the old and new member names. They're 8 characters each and blank padded.
You'd need the address of an open DCB that describes the file you're looking at. You can get the DCB address from the FILE structure, I believe - or you could just open a second DCB to the DDNAME you have allocated.
You'd call the system STOW service with the parameters that tell it to rename a PDS/PDSE member:
STOW dcb,area_from_step1,C
In the STOW macro above, the "directory option" of "C" tells STOW that you want to rename an existing member. The area_from_step1 has the current and new member names - the system searches the directory for the current name and rewrites it with the new member name in place.
To be honest, what I describe above is exactly what the system runtime should be doing, but if it's not and IBM doesn't want to fix it, then you might prefer to do this sort of thing "by hand".

Not sure if this will work, but since you have the dataset already allocated, perhaps you could "call" (for some value of call) IEHPROGM from your program, constucting the proper SYSIN before making the call?
Here's a link to the IBM example for IEHPROGM (mind any break):
https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.idau100/u1354.htm
--Scott

Related

How can I maintain a collection of fish functions in a single file?

I want to define a number of functions for use from the command line and in scripts. One way would be to create one file for every function, and store them in the autoloading folder (e.g. ~/config/fish/functions/one.fish, ~/config/fish/functions/two.fish, ...)
But I don't want to maintain each function in its own file. Is there any way to define a collection of functions in a single file (such that they can be referenced from the command line and from multiple scripts)?
(Alternatively, fish is guided by strong design principles. If there is a documented fish-was-designed-this-way rationale to store one file per user-defined function, I'd like to see it.)
You can just have multiple functions in a single file, but you can only use autoloading for one of them.
The issue is this: If you have a function "foo" and a function "bar" in a file, how is fish supposed to know that, without reading the file first?
For autoloading, the file is named after the function (e.g. "bar" would be stored in "bar.fish"), so fish can figure out where it is.
So, you can do one of two things:
If one of the functions is always called first, then you can use that as the file name and store it in a function file. After you've used that function, fish knows about the rest (since it sourced the file).
If that isn't the case (or you don't want to rely on it), you can either source the file manually whenever you need it (or just once at startup) or store it in a configuration snippet in ~/.config/fish/conf.d/SOMETHING.fish (which fish will source automatically right before reading config.fish).
The former means that e.g. helper functions can be stored along with the main one. The latter is a teensy bit slower when you're loading the file without using the function, but unless you're using this excessively you're unlikely to even notice.

Siemens S5 to S7 XR.INI file

I'm trying to convert a program from S5 to S7. I've taken a look into the tutorials and documents that are available. But I cant seem to find any information about this problem:
The program is pretty complicated and I should need the XR.INI file to convert it with the S5 Converter program that came with Simatic S7. When I open the folder with the project I see all the files I need and that are described in the tutorial made by Siemens.
.ST.S5D
.XR.INI
.Z0.SEQ
I start the converter and open .ST.S5D. When I did this I get the error there is no .XR.INI file. But I can see it in the folder. Its called CERMST.INI. So I guess the name isnt correct?
In PG2000 I remade the XRF with CTRL Q but nothing changed. I also tried to rename the file to CERM.XR.INI because I saw somewhere these files can only be 6 characters long (not sure if this is true).
I tried first without the XRF. There were some errors because of the ASM command. In the tutorial I saw the converter cant handle these so I removed these functions from the program to rewrite manually later on. After this I had an error because I had no XRF. Error was:
Error No PLC type description found for called or addressed block
So I really need the .XR.INI file but the program can't find it, but its clearly in the folder. How can I fix this? How can I make a new .INI file?
Link to tutorial: http://www.sankotek.com/TR/Dokumanlar/STEP%207%20-%20From%20S5%20to%20S7.pdf
Thanks in advance!
Siemens S5 file extensions used also last two letters before file extension to mark file type, like xxxxxxXX.XXX where x is file name and X is file type for S5, without second dot in the middle like you have. File name length limit exists, I think it comes from DOS or some older operating system file length limit.
If you don't have XRF file then if i remember correctly compiler does not have compile order. Some blocks have not been compiled but are referenced in caller block that the compiler tries to compile. Compiler does not find called block in compiled blocks folder and wham... fatal error. When i had such troubles i compiled called blocks independenly before calling blocks. So you can do without XRF file. But try to include Z0.SEQ, that file has assignment list so you get nice variable names instead of just variable address numbers.
Also, stackoverflow is not the correct place to ask questions about Siemens S5-S7 conversion. You should post your questions in http://www.plctalk.net, they have guys there who used to program S5 plc-s.

When and how might the operating system store a file under a different name than I gave it?

I found this statement under another SO question concerning Unicode and I'd like to ask for further elaboration of this rather surprising fact.
Code that believes once you successfully create a file by a given name, that when you run ls or readdir on its enclosing directory,
you'll actually find that file with the name you created it under is
buggy, broken, and wrong. Stop being surprised by this!
When does this happen and what to do about it?
The first example which comes to my mind: If you create a file under OSX that is named é (single U+00E9 codepoint), the OS will store it actually as U+0065 U+0301 (Unicode decomposition). The file will be still accessible under the original name, but listed as decomposed.
How to avoid: don't lookup your files manually unless you are sure their names are pure ASCII.
Second: On Windows, if you have a file called e, try creating (with overwriting enabled) a file called E, the OS will still list a file called e. If e didn't exists beforehand, a file called E would be created.
How to avoid: don't lookup your files manually unless you are sure their names are pure ASCII, and take case into account. Try using a consistent capitalisation style. I suggest going all lowercase.
Third: on Windows, if for example you have Windows 1250 as your system encoding, and you want to create a file named ê via the narrow, char-based API, a file called e will be created instead. This of course is easy to avoid, but this exact problem bit me once: WinRAR extracted files ê.png, è.png and e.png all into e.png, overwriting data. Similar problems can happen with other encoding mixups, too.
How to avoid: don't use API's that take the filename as a char* on Windows.

How to replace a file inside a zip on iOS?

I need to replace a file on a zip using iOS. I tried many libraries with no results. The only one that kind of did the trick was zipzap (https://github.com/pixelglow/zipzap) but this one is no good for me, because what really do is re-zip the file again with the change and besides of this process be to slow for me, also do something that loads the whole file on memory and make my application crash.
PS: If this is not possible or way to complicated, I can settle for rename or delete an specific file.
You need to find a framework where you can modify how data is read and written. You would then use some form of mmap to essentially read and write small chunks. Searching on NSData and mmap resulted in this Post, however you can use mmap from the posix level too. Ps it will be slower than using pure memory no way around that.
Got it WORKING!! JXZip (https://github.com/JanX2/JXZip) has made exactly what I need, they link to libzip (http://www.nih.at/libzip/) that is a fully equiped library for working with ZIP files and JXZip have all the necessary Objective-C wrapper code. Thanks for all the replys.
For archive purposes, as the author of zipzap:
Actually zipzap does exactly what you want. If you replace an entry within a zip file, zipzap will do the minimum necessary to update it: it will skip writing all entries before the replaced entry, then write out the entry, then write out all entries after the replaced entry without recompressing. At the moment, it does require sufficient memory for the entries after the replaced entry though.

Configuration Key Value Store

I'm in the planning stages of a script/app that I'm going to need to write soon. In short, I'm going to have a configuration file that stores multiple key value pairs for a system configuration. Various applications will talk to this file including python/shell/rc scripts.
One example case would be that when the system boots, it pulls the static IP to assign to itself from that file. This means it would be nice to quickly grab a key/value from this file in a shell/rc script (ifconfig `evalconffile main_interface` `evalconffile primary_ip` up), where evalconffile is the script that fetches the value when provided with a key.
I'm looking for suggestions on the best way to approach this. I've tossed around the idea of using a plain text file and perl to retrieve the value. I've also tossed around the idea of using YAML for the configuration file since there may end up being a use case where we need multiple values for a key and general expansion. I know YAML would make it accessible from python and perl, but I'm not sure what the best way to access it from a quickly access it from a shell/rc script would be.
Am I headed in the right direction?
One approach would be to simply do the YAML as you wanted, and then when a shell/RC wants a key/value pair, they would call a small Perl script (the evalconffile in your example) that would parse YAML on the shell script's behalf and print out the value(s)
SQLite will give you greatest flexibility, since you don't seem to know the scope of what will be stored in there. It appears there's support for it in all scripting languages you mentioned.