How does operating system distinguish between file and directory - operating-system

I was going through basics of File System implementation. While implementing for looking up for a file, how does the OS distinguish a file and the directory which it is in?
For example: If I want to lookup a file foo.c with the given path: /home/mac/work/foo.c, How does the OS decide home,mac and work are directories and foo.c is the file inside work directory

I will assume this question pertains to Linux operating systems.
A file by definition is at leaf-level of a tree. Therefore, anything that is suffixed with a / cannot be a file.
The leaf is another story. foo.c might be a file or it might be a directory. The OS has to look at it in order to determine which it is. Internally, a directory is technically a file, but it behaves differently.
To complicate things, Linux has soft- and hard-links, which are special files that can link to a file or directory. And indeed a directory might be the mount point for an entire file system. It's quite common to mount a separate partition or drive as /home. You don't really have to worry about these. You are mostly concerned with the addressing.
If you want to find out what a file is in Linux, use /usr/bin/stat.

Related

Cleanup Perl script should not delete a directory that is symlinked to

A cleanup Perl script running periodically deletes old log files, and if the folder is empty, it deletes the folder as well. Unfortunately, there is one exception: it should not delete a directory that is symlinked to.
There's no way to tell if there exists a symlink that directly references a dir. (Same for indirect references.)
The best you could do is check every single file on the entire file system, but even that monumental effort wouldn't be perfect. For example, it won't find symlinks on devices that aren't currently mounted, it won't find foreign symlinks to shared portions of the file system, etc.

How do I shim executables with the same names in different directories?

I am creating a Chocolatey package for internal team usage. (In this case, the package is for Microsoft's windows debuggers.)
Windows Debuggers contains two folders, one for 32-bit x86 executables and an x64 folder for 64-bit executables.
The executable names are identical.
x86\adplus.exe
x64\adplus.exe
After installation it looks like the shim created by Chocolatey is indeed starting one of the adplus instances successfully. But sometimes I need the 32-bit version and sometimes I need the 64-bit version.
So here is the question: When there are two identically named executables in different directories, how do I tell Chocolately to create different shims for the executables in each directory?
The short answer is that you can't have two identically named shims in the Chocolatey shim folder ($env:ChocolateyInstall\bin).
A limitation of Windows for a directory is that each file/folder must be a unique name. This is what you are running into. Shims get dropped into the $env:ChocolateyInstall\bin folder, which puts them on the PATH automatically because $env:ChocolateyInstall\bin is on the PATH (it allows folks to install all kinds of things without overloading the PATH environment variables).
You can create an empty file ending in .ignore (e.g x86\adplus.exe.ignore) file next to the one you don't want to be shimmed. This is documented on the wiki. You can even do it programmatically during install based on something like OS architecture.
It sounds like you have a need for one of them sometimes and the other at other times on the SAME machine. I would suggest .ignore files for both files, and likely using Get-BinRoot to push the files to a tools folder (you get to define where the location of this is). Then you can set the process PATH temporarily for whichever one you need and it doesn't persist to the actual path. You can even set one on the path and then override it when you want the other.
Since the automation scripts are just PowerShell, you have all kinds of options here.

Hash value MD5 and SHA256 of file is coming different when file is from system32 folder. Why?

I calculated MD5 and SHA256 hash values of notepad.exe and mspaint.exe through online hash generators md5FileCalculator Onlinemd5.
What i noticed is that if i calculate when both exe's are present in their actual postion in system32 the value coming is different than when placed somewhere out of system32 folder.
What is the reason behind that ? Which is the correct hash value ?
I am using Software Restriction policy to block the applications, I created a hash rule for notepad.exe(present in SYSTE32 folder) file and blocked it. When I check the hash value in registry it is different from the hash value of notepad.exe (from SYSTEM32 folder) calculated through other methods like online md5 calculators or through Windows API. But when I copy the notepad.exe file into some other folder say on desktop and calculate the hash value, it is coming same as it is in registry for which I created the rule.So the correct value is I think the one which I get when file is out of system32 folder. But I am not getting why it is happening ? Does it have something to do with permissions ?
It's because of 32-bit applications running on 64-bit Windows, and how Windows handles the System32 folder for those programs.
This was also driving me nuts for a while because I couldn't for the life of me figure out why certain files in System32 (namely .dlls and .exes) were returning different hashes depending on what I checked them with.
Using HxD and Firefox to upload a file to check its hash, I got different results compared to using QTTabBar's hash checker, which runs inside explorer.exe.
But if I copied one of these files to another location, I would then get identical results across all programs.
Meanwhile, HxD showed different file lengths for the copied file vs the one in System32, and while both showed similar byte distribution, there were also significant differences.
But then I thought to try the same thing on another folder, and finally cracked it, with a little help from Wikipedia:
The operating system uses the %SystemRoot%\System32 directory for its
64-bit library and executable files. This is done for backward
compatibility reasons, as many legacy applications are hardcoded to
use that path. When executing 32-bit applications, WoW64 transparently
redirects 32-bit DLLs to %SystemRoot%\SysWOW64, which contains 32-bit
libraries and executables.
32-bit applications are generally not aware
that they are running on a 64-bit operating system. 32-bit
applications can access %SystemRoot%\System32 through the pseudo
directory %SystemRoot%\Sysnative.
Because HxD and Firefox (and most other browsers) are all 32-bit applications, when you load a file into them, Windows is actually transparently redirecting them to the file of the same name in the SysWOW64 folder (presumably if you ran a 64-bit browser, you would not encounter this problem).
Similarly, when you copy a file out of System32 to another location, explorer.exe, being a 64-bit process, copies the original System32 file, and not the (confusingly named) SysWOW64 equivalent.
So as the wiki states, if you enter %SystemRoot%\Sysnative
into the path of the open file dialogue in your 32-bit application, it should load the file from the real System32 folder, and give you the correct result.
And if you check the files in the SysWOW64 directory, all files should return the same respective hashes regardless of what you open them with.
Further reading:
SysWOW64
Sysnative
Are you sure you're checking the exact same file yet on diferent paths? I think you're checking two diferent notepad.exe. Check the size of the file... it must be exacly the same on bytes.
I've just checked my notepad.exe on two distinct paths C:\Windows\System32 and C:\Windows and they are diferent.

Can I move a Perl installation from one computer to another computer?

I am trying to set up an application dependant on few Perl modules, but the server I am installing to, does not have Internet connection. I read about offline module installs via ppd files, however I would have to resolve all the dependencies one by one.. All the more tedious considering I don't have direct internet connection.
I am hoping to find a solution, where I install ActivePerl on my PC and install all the libraries that I want and then copy paste the directories to my server. If it is just a matter of fixing some environment variables, that would be fine. Just want to know the definitive list of variables to modify. Not sure whether it is mandatory to install the perl libraries on the computer in which it is intended to run? (One is 32 bit platform and other one is 64 bit, but the server is already running various 32 bit applications so I hope it is not a major problem) For best compatibility, I plan to install ActivePerl on both the systems and merge the library directories to be identical.
The answer was on Perl FAQ, my bad didn't go through it properly.
I copied the perl binary from one machine to another, but scripts don't work.
That's probably because you forgot libraries, or library paths differ.
You really should build the whole distribution on the machine it will
eventually live on, and then type "make install". Most other approaches
are doomed to failure.
One simple way to check that things are in the right place is to print
out the hard-coded #INC that perl looks through for libraries:
% perl -le 'print for #INC'
If this command lists any paths that don't exist on your system, then
you may need to move the appropriate libraries to these locations, or
create symbolic links, aliases, or shortcuts appropriately. #INC is also
printed as part of the output of
% perl -V
You might also want to check out "How do I keep my own module/library
directory?" in perlfaq8.
From this link
Occasionally, you will not be able to
use any of the methods to install
modules. This may be the case if you
are a particularly under-privileged
user - perhaps you are renting web
space on a server, where you are not
given rights to do anything.
It is possible, for some modules, to
install the module without compiling
anything, and so you can just drop the
file in place and have it work.
Without going into a lot of the
detail, some Perl modules contain a
portion written in some other language
(such as C or C++) and some are
written in just in Perl. It is the
latter type that this method will work
for. How will you know? Well, if there
are no files called something.c and
something.h in the package, chances
are that it is a module that contains
only Perl code.
In these cases, you can just unpack
the file, and then copy just the *.pm
files to a directory from which you
will run the modules. Two examples of
this should suffice to illustrate how
this is done.
IniConf.pm is a wonderful little
module that allows you to read
configuration information out of a
.ini-style config file. IniConf.pm is
written only in Perl, and has no C
portion. When you unpack the .tar.gz
file that you got from CPAN, you will
find several files in there, and one
of them is called IniConf.pm. This is
the only file that you are actually
interested in. Copy that file to the
directory where you have the Perl
programs that will be using this
module. You can then use the module as
you would if it was installed
``correctly,'' with just the line:
use IniConf;
Time::CTime is another very handy
module that lets you print times in
any format that strikes your fancy. It
is written just in Perl, without a C
component. You will install it just
the same way as you did with IniConf,
except that the file, called CTime.pm,
must be placed in a subdirectory
called Time. The colons, as well as
indicating an organization of modules,
also indicates a directory structure
on your file system.

Should I check in *.mo files?

Should I check in *.mo translation files into my version control system?
This is a general question. But in particular I'm working on Django projects with git repositories.
The general answer is:
if you do need those files to compile or to deploy (in shot: to "work" with) your component (set of files queried from your VCS), then yes, they should be stored in it (here: in Git).
This is the same for other kind of files (like project files for instance)
.mo files are particular:
django-admin.py compilemessages utility.
This tool runs over all available .po files and creates .mo files, which are binary files optimized for use by gettext
Meaning:
you should be able to rebuild them every time you need them (guarantying in effect that they are in synch with their .po couterparts)
Git is not so good with binary storage and that would avoid it to store a full version for every changes
So the specific answer is not so clear-cut:
if your po files are stables and will not evolve too often, you could definitively store the .mo file
you should absolutely store a big README file explaning how to generate mo from po files.
The general answer is to not store generated contents in version control.
You can include it in tarball, if it requires rare tools, or even have separate repository or disconnected branch with only those generated files (like 'html' and 'man' branches in git.git repository).
For asked question Jakub answer is pretty neat.
But one could ask:
So where should I store such files? Should I generate them every time I deploy my code?
And for that... it depends. You could deploy it in tarball (as Jakub sugested) or even better - create pip or system package (RPM for fedora, DEB for debian, etc.).