int createfile(AFPObj *obj, uint16_t vid, cnid_t did, const char *name) { const int bufsize = 256; char buf[bufsize]; char *p = buf; int len = 0; PUSHVAL(p, uint16_t, htons(128), len); /* hard create */ PUSHVAL(p, uint16_t, vid, len); PUSHVAL(p, cnid_t, did, len); len += push_path(&p, name); return afp_createfile(obj, buf, len, rbuf, &rbuflen); }
int ml_creat(struct afp_volume * volume, const char *path, mode_t mode) { int ret=0; char basename[AFP_MAX_PATH]; unsigned int dirid; struct afp_file_info fp; int rc; char converted_path[AFP_MAX_PATH]; if (convert_path_to_afp(volume->server->path_encoding, converted_path,(char *) path,AFP_MAX_PATH)) return -EINVAL; if (volume_is_readonly(volume)) return -EACCES; ret=appledouble_creat(volume,path,mode); if (ret<0) return ret; if (ret==1) return 0; if (invalid_filename(volume->server,converted_path)) return -ENAMETOOLONG; get_dirid(volume, converted_path, basename, &dirid); rc=afp_createfile(volume,kFPSoftCreate, dirid,basename); switch(rc) { case kFPAccessDenied: ret=EACCES; break; case kFPDiskFull: ret=ENOSPC; break; case kFPObjectExists: ret=EEXIST; break; case kFPObjectNotFound: ret=ENOENT; break; case kFPFileBusy: case kFPVolLocked: ret=EBUSY; break; case kFPNoErr: ret=0; break; default: case kFPParamErr: case kFPMiscErr: ret=EIO; } if (ret) return -ret; /* If we don't support unixprivs, just exit */ if (~ volume->extra_flags & VOLUME_EXTRA_FLAGS_VOL_SUPPORTS_UNIX) return 0; /* Figure out the privs of the file we just created */ if ((ret=get_unixprivs(volume, dirid,basename, &fp))) return rc; if (ret) return -ret; if (fp.unixprivs.permissions==mode) return 0; fp.unixprivs.ua_permissions=0; fp.unixprivs.permissions=mode; fp.isdir=0; /* Anything you make with mknod is a file */ /* note that we're not monkeying with the ownership here */ rc=set_unixprivs(volume, dirid, basename, &fp); switch(rc) { case kFPAccessDenied: ret=EPERM; goto error; case kFPObjectNotFound: ret=ENOENT; goto error; case 0: ret=0; break; case kFPBitmapErr: case kFPMiscErr: case kFPObjectTypeErr: case kFPParamErr: default: ret=EIO; goto error; } error: return -ret; }
int ml_symlink(struct afp_volume *vol, const char * path1, const char * path2) { int ret; struct afp_file_info fp; uint64_t written; int rc; unsigned int dirid2; char basename2[AFP_MAX_PATH]; char converted_path1[AFP_MAX_PATH]; char converted_path2[AFP_MAX_PATH]; if (vol->server->using_version->av_number<30) { /* No symlinks for AFP 2.x. */ ret=ENOSYS; goto error; } /* Yes, you can create symlinks for AFP >=30. Tested with 10.3.2 */ if (convert_path_to_afp(vol->server->path_encoding, converted_path1,(char *) path1,AFP_MAX_PATH)) return -EINVAL; if (convert_path_to_afp(vol->server->path_encoding, converted_path2,(char *) path2,AFP_MAX_PATH)) return -EINVAL; if (volume_is_readonly(vol)) return -EACCES; ret=appledouble_symlink(vol,path1,path2); if (ret<0) return ret; if (ret==1) return 0; get_dirid(vol,converted_path2,basename2,&dirid2 ); /* 1. create the file */ rc=afp_createfile(vol,kFPHardCreate,dirid2,basename2); switch (rc) { case kFPAccessDenied: ret=EACCES; goto error; case kFPDiskFull: ret=ENOSPC; goto error; case kFPObjectExists: ret=EEXIST; goto error; case kFPObjectNotFound: ret=ENOENT; goto error; case kFPFileBusy: case kFPVolLocked: ret=EBUSY; goto error; case kFPNoErr: ret=0; break; default: case kFPParamErr: case kFPMiscErr: ret=EIO; goto error; } /* Open the fork */ rc=afp_openfork(vol,0, dirid2, AFP_OPENFORK_ALLOWWRITE|AFP_OPENFORK_ALLOWREAD, basename2,&fp); switch (ret) { case kFPAccessDenied: ret=EACCES; goto error; case kFPObjectNotFound: ret=ENOENT; goto error; case kFPObjectLocked: ret=EROFS; goto error; case kFPObjectTypeErr: ret=EISDIR; goto error; case kFPParamErr: ret=EACCES; goto error; case kFPTooManyFilesOpen: ret=EMFILE; goto error; case 0: ret=0; break; case kFPVolLocked: case kFPDenyConflict: case kFPMiscErr: case kFPBitmapErr: case -1: default: ret=EFAULT; goto error; } add_opened_fork(vol, &fp); /* Write the name of the file to it */ rc=afp_writeext(vol,fp.forkid,0,strlen(converted_path1), converted_path1,&written); switch(afp_closefork(vol,fp.forkid)) { case kFPNoErr: break; default: case kFPParamErr: case kFPMiscErr: ret=EIO; goto error; } remove_opened_fork(vol, &fp); /* And now for the undocumented magic */ memset(&fp.finderinfo,0,32); fp.finderinfo[0]='s'; fp.finderinfo[1]='l'; fp.finderinfo[2]='n'; fp.finderinfo[3]='k'; fp.finderinfo[4]='r'; fp.finderinfo[5]='h'; fp.finderinfo[6]='a'; fp.finderinfo[7]='p'; rc=afp_setfiledirparms(vol,dirid2,basename2, kFPFinderInfoBit, &fp); switch (rc) { case kFPAccessDenied: ret=EPERM; goto error; case kFPBitmapErr: /* This is the case where it isn't supported */ ret=ENOSYS; goto error; case kFPObjectNotFound: ret=ENOENT; goto error; case 0: ret=0; break; case kFPMiscErr: case kFPObjectTypeErr: case kFPParamErr: default: ret=EIO; goto error; } error: return -ret; };