/* Copyright (c) 2004-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifdef MSW #include #else #include #endif #include #include #include #include "m_pd.h" #include "os.h" static int ospath_doabsolute(char *path, char *cwd, char *result) { if (*path == 0) { if (result) strcpy(result, cwd); else return (strlen(cwd)); } else if (*path == '~') { path++; if (*path == '/' || *path == 0) { #ifdef UNIX char *home = getenv("HOME"); if (home) { if (result) { strcpy(result, home); if (*path) strcat(result, path); } else return (strlen(home) + strlen(path)); } else goto badpath; #else goto badpath; #endif } else goto badpath; } else if (*path == '/') { #ifdef MSW /* path is absolute, drive is implicit, LATER UNC? */ if (*cwd && cwd[1] == ':') { if (result) { *result = *cwd; result[1] = ':'; strcpy(result + 2, path); } else return (2 + strlen(path)); } else goto badpath; #else /* path is absolute */ if (result) strcpy(result, path); else return (strlen(path)); #endif } else { #ifdef MSW if (path[1] == ':') { if (path[2] == '/') { /* path is absolute */ if (result) strcpy(result, path); else return (strlen(path)); } else if (*cwd == *path) { /* path is relative, drive is explicitly current */ if (result) { int ndx = strlen(cwd); strcpy(result, cwd); result[ndx++] = '/'; strcpy(result + ndx, path + 2); } else return (strlen(cwd) + strlen(path) - 1); } /* we do not maintain per-drive cwd, LATER rethink */ else goto badpath; } /* LATER devices? */ else { /* path is relative */ if (result) { int ndx = strlen(cwd); strcpy(result, cwd); result[ndx++] = '/'; strcpy(result + ndx, path); } else return (strlen(cwd) + 1 + strlen(path)); } #else /* path is relative */ if (result) { int ndx = strlen(cwd); strcpy(result, cwd); result[ndx++] = '/'; strcpy(result + ndx, path); } else return (strlen(cwd) + 1 + strlen(path)); #endif } if (result && *result && *result != '.') { /* clean-up */ char *inptr, *outptr = result; int ndx = strlen(result); if (result[ndx - 1] == '.') { result[ndx] = '/'; /* guarding slash */ result[ndx + 1] = 0; } for (inptr = result + 1; *inptr; inptr++) { if (*inptr == '/') { if (*outptr == '/') continue; else if (*outptr == '.') { if (outptr[-1] == '/') { outptr--; continue; } else if (outptr[-1] == '.' && outptr[-2] == '/') { outptr -= 2; if (outptr == result) continue; else for (outptr--; outptr != result; outptr--) if (*outptr == '/') break; continue; } } } *++outptr = *inptr; } if (*outptr == '/' && outptr != result) *outptr = 0; else outptr[1] = 0; } else bug("ospath_doabsolute 1"); return (0); badpath: if (result) bug("ospath_doabsolute 2"); return (0); } /* Returns an estimated length of an absolute path made up from the first arg. The actual ospath_absolute()'s length may be shorter (since it erases superfluous slashes and dots), but not longer. Both args should be unbashed (system-independent), cwd should be absolute. Returns 0 in case of any error (LATER revisit). */ int ospath_length(char *path, char *cwd) { /* one extra byte used internally (guarding slash) */ return (ospath_doabsolute(path, cwd, 0) + 1); } /* Copies an absolute path to result. Arguments: path and cwd, are the same as in ospath_length(). Caller should first consult ospath_length(), and allocate at least ospath_length() + 1 bytes to the result buffer. Should never fail (failure is a bug). */ char *ospath_absolute(char *path, char *cwd, char *result) { ospath_doabsolute(path, cwd, result); return (result); } FILE *fileread_open(char *filename, t_canvas *cv, int textmode) { int fd; char path[MAXPDSTRING+2], *nameptr; t_symbol *dirsym = (cv ? canvas_getdir(cv) : 0); /* path arg is returned unbashed (system-independent) */ if ((fd = open_via_path((dirsym ? dirsym->s_name : ""), filename, "", path, &nameptr, MAXPDSTRING, 1)) < 0) return (0); /* Closing/reopening dance. This is unnecessary under linux, and we could have tried to convert fd to fp, but under windows open_via_path() returns what seems to be an invalid fd. LATER try to understand what is going on here... */ close(fd); if (path != nameptr) { char *slashpos = path + strlen(path); *slashpos++ = '/'; /* try not to be dependent on current open_via_path() implementation */ if (nameptr != slashpos) strcpy(slashpos, nameptr); } sys_bashfilename(path, path); return (fopen(path, (textmode ? "r" : "rb"))); } FILE *filewrite_open(char *filename, t_canvas *cv, int textmode) { char path[MAXPDSTRING+2]; if (cv) /* path arg is returned unbashed (system-independent) */ canvas_makefilename(cv, filename, path, MAXPDSTRING); else { strncpy(path, filename, MAXPDSTRING); path[MAXPDSTRING-1] = 0; } sys_bashfilename(path, path); return (fopen(path, (textmode ? "w" : "wb"))); }